stype.c

00001 /*
00002  * Copyright (c) 2011 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <assert.h>
00040 #include "cspan.h"
00041 #include "debug.h"
00042 #include "intmap.h"
00043 #include "list.h"
00044 #include "mytypes.h"
00045 #include "run_texpr.h"
00046 #include "stree.h"
00047 #include "strtab.h"
00048 #include "stype_expr.h"
00049 #include "symbol.h"
00050 #include "tdata.h"
00051 
00052 #include "stype.h"
00053 
00054 static void stype_csi(stype_t *stype, stree_csi_t *csi);
00055 static void stype_ctor(stype_t *stype, stree_ctor_t *ctor);
00056 static void stype_ctor_body(stype_t *stype, stree_ctor_t *ctor);
00057 static void stype_fun(stype_t *stype, stree_fun_t *fun);
00058 static void stype_var(stype_t *stype, stree_var_t *var);
00059 static void stype_prop(stype_t *stype, stree_prop_t *prop);
00060 
00061 static void stype_fun_sig(stype_t *stype, stree_csi_t *outer_csi,
00062     stree_fun_sig_t *sig, tdata_fun_sig_t **rtsig);
00063 static void stype_fun_body(stype_t *stype, stree_fun_t *fun);
00064 static void stype_block(stype_t *stype, stree_block_t *block);
00065 
00066 static void stype_class_impl_check(stype_t *stype, stree_csi_t *csi);
00067 static void stype_class_impl_check_if(stype_t *stype, stree_csi_t *csi,
00068     tdata_item_t *iface_ti);
00069 static void stype_class_impl_check_mbr(stype_t *stype, stree_csi_t *csi,
00070     tdata_tvv_t *if_tvv, stree_csimbr_t *ifmbr);
00071 static void stype_class_impl_check_fun(stype_t *stype,
00072     stree_symbol_t *cfun_sym, tdata_tvv_t *if_tvv, stree_symbol_t *ifun_sym);
00073 static void stype_class_impl_check_prop(stype_t *stype,
00074     stree_symbol_t *cprop_sym, tdata_tvv_t *if_tvv, stree_symbol_t *iprop_sym);
00075 
00076 static void stype_vdecl(stype_t *stype, stree_vdecl_t *vdecl_s);
00077 static void stype_if(stype_t *stype, stree_if_t *if_s);
00078 static void stype_switch(stype_t *stype, stree_switch_t *switch_s);
00079 static void stype_while(stype_t *stype, stree_while_t *while_s);
00080 static void stype_for(stype_t *stype, stree_for_t *for_s);
00081 static void stype_raise(stype_t *stype, stree_raise_t *raise_s);
00082 static void stype_break(stype_t *stype, stree_break_t *break_s);
00083 static void stype_return(stype_t *stype, stree_return_t *return_s);
00084 static void stype_exps(stype_t *stype, stree_exps_t *exp_s, bool_t want_value);
00085 static void stype_wef(stype_t *stype, stree_wef_t *wef_s);
00086 
00087 static stree_expr_t *stype_convert_tprimitive(stype_t *stype,
00088     stree_expr_t *expr, tdata_item_t *dest);
00089 static stree_expr_t *stype_convert_tprim_tobj(stype_t *stype,
00090     stree_expr_t *expr, tdata_item_t *dest);
00091 static stree_expr_t *stype_convert_tobject(stype_t *stype, stree_expr_t *expr,
00092     tdata_item_t *dest);
00093 static stree_expr_t *stype_convert_tarray(stype_t *stype, stree_expr_t *expr,
00094     tdata_item_t *dest);
00095 static stree_expr_t *stype_convert_tdeleg(stype_t *stype, stree_expr_t *expr,
00096     tdata_item_t *dest);
00097 static stree_expr_t *stype_convert_tenum(stype_t *stype, stree_expr_t *expr,
00098     tdata_item_t *dest);
00099 static stree_expr_t *stype_convert_tfun_tdeleg(stype_t *stype,
00100     stree_expr_t *expr, tdata_item_t *dest);
00101 static stree_expr_t *stype_convert_tvref(stype_t *stype, stree_expr_t *expr,
00102     tdata_item_t *dest);
00103 
00104 static bool_t stype_fun_sig_equal(stype_t *stype, tdata_fun_sig_t *asig,
00105     tdata_fun_sig_t *sdig);
00106 
00115 void stype_module(stype_t *stype, stree_module_t *module)
00116 {
00117         list_node_t *mbr_n;
00118         stree_modm_t *mbr;
00119 
00120 #ifdef DEBUG_TYPE_TRACE
00121         printf("Type module.\n");
00122 #endif
00123         stype->current_csi = NULL;
00124         stype->proc_vr = NULL;
00125 
00126         mbr_n = list_first(&module->members);
00127         while (mbr_n != NULL) {
00128                 mbr = list_node_data(mbr_n, stree_modm_t *);
00129 
00130                 switch (mbr->mc) {
00131                 case mc_csi:
00132                         stype_csi(stype, mbr->u.csi);
00133                         break;
00134                 case mc_enum:
00135                         stype_enum(stype, mbr->u.enum_d);
00136                         break;
00137                 }
00138 
00139                 mbr_n = list_next(&module->members, mbr_n);
00140         }
00141 }
00142 
00148 static void stype_csi(stype_t *stype, stree_csi_t *csi)
00149 {
00150         list_node_t *csimbr_n;
00151         stree_csimbr_t *csimbr;
00152         stree_csi_t *prev_ctx;
00153 
00154 #ifdef DEBUG_TYPE_TRACE
00155         printf("Type CSI '");
00156         symbol_print_fqn(csi_to_symbol(csi));
00157         printf("'.\n");
00158 #endif
00159         prev_ctx = stype->current_csi;
00160         stype->current_csi = csi;
00161 
00162         csimbr_n = list_first(&csi->members);
00163         while (csimbr_n != NULL) {
00164                 csimbr = list_node_data(csimbr_n, stree_csimbr_t *);
00165 
00166                 switch (csimbr->cc) {
00167                 case csimbr_csi: stype_csi(stype, csimbr->u.csi); break;
00168                 case csimbr_ctor: stype_ctor(stype, csimbr->u.ctor); break;
00169                 case csimbr_deleg: stype_deleg(stype, csimbr->u.deleg); break;
00170                 case csimbr_enum: stype_enum(stype, csimbr->u.enum_d); break;
00171                 case csimbr_fun: stype_fun(stype, csimbr->u.fun); break;
00172                 case csimbr_var: stype_var(stype, csimbr->u.var); break;
00173                 case csimbr_prop: stype_prop(stype, csimbr->u.prop); break;
00174                 }
00175 
00176                 csimbr_n = list_next(&csi->members, csimbr_n);
00177         }
00178 
00179         if (csi->cc == csi_class)
00180                 stype_class_impl_check(stype, csi);
00181 
00182         stype->current_csi = prev_ctx;
00183 }
00184 
00190 static void stype_ctor(stype_t *stype, stree_ctor_t *ctor)
00191 {
00192 #ifdef DEBUG_TYPE_TRACE
00193         printf("Type constructor '");
00194         symbol_print_fqn(ctor_to_symbol(ctor));
00195         printf("'.\n");
00196 #endif
00197         if (ctor->titem == NULL)
00198                 stype_ctor_header(stype, ctor);
00199 
00200         stype_ctor_body(stype, ctor);
00201 }
00202 
00208 void stype_ctor_header(stype_t *stype, stree_ctor_t *ctor)
00209 {
00210         stree_symbol_t *ctor_sym;
00211         tdata_item_t *ctor_ti;
00212         tdata_fun_t *tfun;
00213         tdata_fun_sig_t *tsig;
00214 
00215 #ifdef DEBUG_TYPE_TRACE
00216         printf("Type constructor '");
00217         symbol_print_fqn(ctor_to_symbol(ctor));
00218         printf("' header.\n");
00219 #endif
00220         if (ctor->titem != NULL)
00221                 return; /* Constructor header has already been typed. */
00222 
00223         ctor_sym = ctor_to_symbol(ctor);
00224 
00225         /* Type function signature. */
00226         stype_fun_sig(stype, ctor_sym->outer_csi, ctor->sig, &tsig);
00227 
00228         ctor_ti = tdata_item_new(tic_tfun);
00229         tfun = tdata_fun_new();
00230         ctor_ti->u.tfun = tfun;
00231         tfun->tsig = tsig;
00232 
00233         ctor->titem = ctor_ti;
00234 }
00235 
00241 static void stype_ctor_body(stype_t *stype, stree_ctor_t *ctor)
00242 {
00243 #ifdef DEBUG_TYPE_TRACE
00244         printf("Type constructor '");
00245         symbol_print_fqn(ctor_to_symbol(ctor));
00246         printf("' body.\n");
00247 #endif
00248         assert(stype->proc_vr == NULL);
00249 
00250         stype->proc_vr = stype_proc_vr_new();
00251         stype->proc_vr->proc = ctor->proc;
00252         list_init(&stype->proc_vr->block_vr);
00253 
00254         stype_block(stype, ctor->proc->body);
00255 
00256         free(stype->proc_vr);
00257         stype->proc_vr = NULL;
00258 }
00259 
00265 void stype_deleg(stype_t *stype, stree_deleg_t *deleg)
00266 {
00267         stree_symbol_t *deleg_sym;
00268         tdata_item_t *deleg_ti;
00269         tdata_deleg_t *tdeleg;
00270         tdata_fun_sig_t *tsig;
00271 
00272 #ifdef DEBUG_TYPE_TRACE
00273         printf("Type delegate '");
00274         symbol_print_fqn(deleg_to_symbol(deleg));
00275         printf("'.\n");
00276 #endif
00277         if (deleg->titem == NULL) {
00278                 deleg_ti = tdata_item_new(tic_tdeleg);
00279                 deleg->titem = deleg_ti;
00280                 tdeleg = tdata_deleg_new();
00281                 deleg_ti->u.tdeleg = tdeleg;
00282         } else {
00283                 deleg_ti = deleg->titem;
00284                 assert(deleg_ti->u.tdeleg != NULL);
00285                 tdeleg = deleg_ti->u.tdeleg;
00286         }
00287 
00288         if (tdeleg->tsig != NULL)
00289                 return; /* Delegate has already been typed. */
00290 
00291         deleg_sym = deleg_to_symbol(deleg);
00292 
00293         /* Type function signature. Store result in deleg->titem. */
00294         stype_fun_sig(stype, deleg_sym->outer_csi, deleg->sig, &tsig);
00295 
00296         tdeleg->deleg = deleg;
00297         tdeleg->tsig = tsig;
00298 }
00299 
00305 void stype_enum(stype_t *stype, stree_enum_t *enum_d)
00306 {
00307         tdata_item_t *titem;
00308         tdata_enum_t *tenum;
00309 
00310         (void) stype;
00311 
00312 #ifdef DEBUG_TYPE_TRACE
00313         printf("Type enum '");
00314         symbol_print_fqn(enum_to_symbol(enum_d));
00315         printf("'.\n");
00316 #endif
00317         if (enum_d->titem == NULL) {
00318                 titem = tdata_item_new(tic_tenum);
00319                 tenum = tdata_enum_new();
00320                 titem->u.tenum = tenum;
00321                 tenum->enum_d = enum_d;
00322 
00323                 enum_d->titem = titem;
00324         }
00325 }
00326 
00337 static void stype_fun(stype_t *stype, stree_fun_t *fun)
00338 {
00339 #ifdef DEBUG_TYPE_TRACE
00340         printf("Type function '");
00341         symbol_print_fqn(fun_to_symbol(fun));
00342         printf("'.\n");
00343 #endif
00344         if (fun->titem == NULL)
00345                 stype_fun_header(stype, fun);
00346 
00347         stype_fun_body(stype, fun);
00348 }
00349 
00357 void stype_fun_header(stype_t *stype, stree_fun_t *fun)
00358 {
00359         stree_symbol_t *fun_sym;
00360         tdata_item_t *fun_ti;
00361         tdata_fun_t *tfun;
00362         tdata_fun_sig_t *tsig;
00363 
00364 #ifdef DEBUG_TYPE_TRACE
00365         printf("Type function '");
00366         symbol_print_fqn(fun_to_symbol(fun));
00367         printf("' header.\n");
00368 #endif
00369         if (fun->titem != NULL)
00370                 return; /* Function header has already been typed. */
00371 
00372         fun_sym = fun_to_symbol(fun);
00373 
00374         /* Type function signature. */
00375         stype_fun_sig(stype, fun_sym->outer_csi, fun->sig, &tsig);
00376 
00377         fun_ti = tdata_item_new(tic_tfun);
00378         tfun = tdata_fun_new();
00379         fun_ti->u.tfun = tfun;
00380         tfun->tsig = tsig;
00381 
00382         fun->titem = fun_ti;
00383 }
00384 
00393 static void stype_fun_sig(stype_t *stype, stree_csi_t *outer_csi,
00394     stree_fun_sig_t *sig, tdata_fun_sig_t **rtsig)
00395 {
00396         list_node_t *arg_n;
00397         stree_proc_arg_t *arg;
00398         tdata_item_t *titem;
00399         tdata_fun_sig_t *tsig;
00400 
00401 #ifdef DEBUG_TYPE_TRACE
00402         printf("Type function signature.\n");
00403 #endif
00404         tsig = tdata_fun_sig_new();
00405 
00406         list_init(&tsig->arg_ti);
00407 
00408         /*
00409          * Type formal arguments.
00410          */
00411         arg_n = list_first(&sig->args);
00412         while (arg_n != NULL) {
00413                 arg = list_node_data(arg_n, stree_proc_arg_t *);
00414 
00415                 /* XXX Because of overloaded builtin WriteLine. */
00416                 if (arg->type == NULL) {
00417                         list_append(&tsig->arg_ti, NULL);
00418                         arg_n = list_next(&sig->args, arg_n);
00419                         continue;
00420                 }
00421 
00422                 run_texpr(stype->program, outer_csi, arg->type, &titem);
00423                 list_append(&tsig->arg_ti, titem);
00424 
00425                 arg_n = list_next(&sig->args, arg_n);
00426         }
00427 
00428         /* Variadic argument */
00429         if (sig->varg != NULL) {
00430                 /* Check type and verify it is an array. */
00431                 run_texpr(stype->program, outer_csi, sig->varg->type, &titem);
00432                 tsig->varg_ti = titem;
00433 
00434                 if (titem->tic != tic_tarray && titem->tic != tic_ignore) {
00435                         printf("Error: Packed argument is not an array.\n");
00436                         stype_note_error(stype);
00437                 }
00438         }
00439 
00440         /* Return type */
00441         if (sig->rtype != NULL) {
00442                 run_texpr(stype->program, outer_csi, sig->rtype, &titem);
00443                 tsig->rtype = titem;
00444         }
00445 
00446         *rtsig = tsig;
00447 }
00448 
00456 static void stype_fun_body(stype_t *stype, stree_fun_t *fun)
00457 {
00458 #ifdef DEBUG_TYPE_TRACE
00459         printf("Type function '");
00460         symbol_print_fqn(fun_to_symbol(fun));
00461         printf("' body.\n");
00462 #endif
00463         assert(stype->proc_vr == NULL);
00464 
00465         /* Declarations and builtin functions do not have a body. */
00466         if (fun->proc->body == NULL)
00467                 return;
00468 
00469         stype->proc_vr = stype_proc_vr_new();
00470         stype->proc_vr->proc = fun->proc;
00471         list_init(&stype->proc_vr->block_vr);
00472 
00473         stype_block(stype, fun->proc->body);
00474 
00475         free(stype->proc_vr);
00476         stype->proc_vr = NULL;
00477 }
00478 
00484 static void stype_var(stype_t *stype, stree_var_t *var)
00485 {
00486         tdata_item_t *titem;
00487 
00488         run_texpr(stype->program, stype->current_csi, var->type,
00489             &titem);
00490         if (titem->tic == tic_ignore) {
00491                 /* An error occured. */
00492                 stype_note_error(stype);
00493         }
00494 }
00495 
00501 static void stype_prop(stype_t *stype, stree_prop_t *prop)
00502 {
00503 #ifdef DEBUG_TYPE_TRACE
00504         printf("Type property '");
00505         symbol_print_fqn(prop_to_symbol(prop));
00506         printf("'.\n");
00507 #endif
00508         if (prop->titem == NULL)
00509                 stype_prop_header(stype, prop);
00510 
00511         stype->proc_vr = stype_proc_vr_new();
00512         list_init(&stype->proc_vr->block_vr);
00513 
00514         /* Property declarations do not have a getter body. */
00515         if (prop->getter != NULL && prop->getter->body != NULL) {
00516                 stype->proc_vr->proc = prop->getter;
00517                 stype_block(stype, prop->getter->body);
00518         }
00519 
00520         /* Property declarations do not have a setter body. */
00521         if (prop->setter != NULL && prop->setter->body != NULL) {
00522                 stype->proc_vr->proc = prop->setter;
00523                 stype_block(stype, prop->setter->body);
00524         }
00525 
00526         free(stype->proc_vr);
00527         stype->proc_vr = NULL;
00528 }
00529 
00535 void stype_prop_header(stype_t *stype, stree_prop_t *prop)
00536 {
00537         tdata_item_t *titem;
00538 
00539 #ifdef DEBUG_TYPE_TRACE
00540         printf("Type property '");
00541         symbol_print_fqn(prop_to_symbol(prop));
00542         printf("' header.\n");
00543 #endif
00544         run_texpr(stype->program, stype->current_csi, prop->type,
00545             &titem);
00546         if (titem->tic == tic_ignore) {
00547                 /* An error occured. */
00548                 stype_note_error(stype);
00549                 return;
00550         }
00551 
00552         prop->titem = titem;
00553 }
00554 
00560 static void stype_block(stype_t *stype, stree_block_t *block)
00561 {
00562         stree_stat_t *stat;
00563         list_node_t *stat_n;
00564         stype_block_vr_t *block_vr;
00565         list_node_t *bvr_n;
00566 
00567 #ifdef DEBUG_TYPE_TRACE
00568         printf("Type block.\n");
00569 #endif
00570 
00571         /* Create block visit record. */
00572         block_vr = stype_block_vr_new();
00573         intmap_init(&block_vr->vdecls);
00574 
00575         /* Add block visit record to the stack. */
00576         list_append(&stype->proc_vr->block_vr, block_vr);
00577 
00578         stat_n = list_first(&block->stats);
00579         while (stat_n != NULL) {
00580                 stat = list_node_data(stat_n, stree_stat_t *);
00581                 stype_stat(stype, stat, b_false);
00582 
00583                 stat_n = list_next(&block->stats, stat_n);
00584         }
00585 
00586         /* Remove block visit record from the stack, */
00587         bvr_n = list_last(&stype->proc_vr->block_vr);
00588         assert(list_node_data(bvr_n, stype_block_vr_t *) == block_vr);
00589         list_remove(&stype->proc_vr->block_vr, bvr_n);
00590 }
00591 
00597 static void stype_class_impl_check(stype_t *stype, stree_csi_t *csi)
00598 {
00599         list_node_t *pred_n;
00600         stree_texpr_t *pred_te;
00601         tdata_item_t *pred_ti;
00602 
00603 #ifdef DEBUG_TYPE_TRACE
00604         printf("Verify that class implements all interfaces.\n");
00605 #endif
00606         assert(csi->cc == csi_class);
00607 
00608         pred_n = list_first(&csi->inherit);
00609         while (pred_n != NULL) {
00610                 pred_te = list_node_data(pred_n, stree_texpr_t *);
00611                 run_texpr(stype->program, csi, pred_te, &pred_ti);
00612 
00613                 assert(pred_ti->tic == tic_tobject);
00614                 switch (pred_ti->u.tobject->csi->cc) {
00615                 case csi_class:
00616                         break;
00617                 case csi_struct:
00618                         assert(b_false);
00619                 case csi_interface:
00620                         /* Store to impl_if_ti for later use. */
00621                         list_append(&csi->impl_if_ti, pred_ti);
00622 
00623                         /* Check implementation of this interface. */
00624                         stype_class_impl_check_if(stype, csi, pred_ti);
00625                         break;
00626                 }
00627 
00628                 pred_n = list_next(&csi->inherit, pred_n);
00629         }
00630 }
00631 
00638 static void stype_class_impl_check_if(stype_t *stype, stree_csi_t *csi,
00639     tdata_item_t *iface_ti)
00640 {
00641         tdata_tvv_t *iface_tvv;
00642         list_node_t *pred_n;
00643         tdata_item_t *pred_ti;
00644         tdata_item_t *pred_sti;
00645 
00646         stree_csi_t *iface;
00647         list_node_t *ifmbr_n;
00648         stree_csimbr_t *ifmbr;
00649 
00650         assert(csi->cc == csi_class);
00651 
00652         assert(iface_ti->tic == tic_tobject);
00653         iface = iface_ti->u.tobject->csi;
00654         assert(iface->cc = csi_interface);
00655 
00656 #ifdef DEBUG_TYPE_TRACE
00657         printf("Verify that class fully implements interface.\n");
00658 #endif
00659         /* Compute TVV for this interface reference. */
00660         stype_titem_to_tvv(stype, iface_ti, &iface_tvv);
00661 
00662         /*
00663          * Recurse to accumulated interfaces.
00664          */
00665         pred_n = list_first(&iface->impl_if_ti);
00666         while (pred_n != NULL) {
00667                 pred_ti = list_node_data(pred_n, tdata_item_t *);
00668                 assert(pred_ti->tic == tic_tobject);
00669                 assert(pred_ti->u.tobject->csi->cc == csi_interface);
00670 
00671                 /* Substitute real type parameters to predecessor reference. */
00672                 tdata_item_subst(pred_ti, iface_tvv, &pred_sti);
00673 
00674                 /* Check accumulated interface. */
00675                 stype_class_impl_check_if(stype, csi, pred_sti);
00676 
00677                 pred_n = list_next(&iface->impl_if_ti, pred_n);
00678         }
00679 
00680         /*
00681          * Check all interface members.
00682          */
00683         ifmbr_n = list_first(&iface->members);
00684         while (ifmbr_n != NULL) {
00685                 ifmbr = list_node_data(ifmbr_n, stree_csimbr_t *);
00686                 stype_class_impl_check_mbr(stype, csi, iface_tvv, ifmbr);
00687 
00688                 ifmbr_n = list_next(&iface->members, ifmbr_n);
00689         }
00690 }
00691 
00699 static void stype_class_impl_check_mbr(stype_t *stype, stree_csi_t *csi,
00700     tdata_tvv_t *if_tvv, stree_csimbr_t *ifmbr)
00701 {
00702         stree_symbol_t *cmbr_sym;
00703         stree_symbol_t *ifmbr_sym;
00704         stree_ident_t *ifmbr_name;
00705 
00706         assert(csi->cc == csi_class);
00707 
00708 #ifdef DEBUG_TYPE_TRACE
00709         printf("Verify that class implements interface member.\n");
00710 #endif
00711         ifmbr_name = stree_csimbr_get_name(ifmbr);
00712 
00713         cmbr_sym = symbol_search_csi(stype->program, csi, ifmbr_name);
00714         if (cmbr_sym == NULL) {
00715                 printf("Error: CSI '");
00716                 symbol_print_fqn(csi_to_symbol(csi));
00717                 printf("' should implement '");
00718                 symbol_print_fqn(csimbr_to_symbol(ifmbr));
00719                 printf("' but it does not.\n");
00720                 stype_note_error(stype);
00721                 return;
00722         }
00723 
00724         ifmbr_sym = csimbr_to_symbol(ifmbr);
00725         if (cmbr_sym->sc != ifmbr_sym->sc) {
00726                 printf("Error: CSI '");
00727                 symbol_print_fqn(csi_to_symbol(csi));
00728                 printf("' implements '");
00729                 symbol_print_fqn(csimbr_to_symbol(ifmbr));
00730                 printf("' as a different kind of symbol.\n");
00731                 stype_note_error(stype);
00732         }
00733 
00734         switch (cmbr_sym->sc) {
00735         case sc_csi:
00736         case sc_ctor:
00737         case sc_deleg:
00738         case sc_enum:
00739                 /*
00740                  * Checked at parse time. Interface should not have these
00741                  * member types.
00742                  */
00743                 assert(b_false);
00744         case sc_fun:
00745                 stype_class_impl_check_fun(stype, cmbr_sym, if_tvv, ifmbr_sym);
00746                 break;
00747         case sc_var:
00748                 /*
00749                  * Checked at parse time. Interface should not have these
00750                  * member types.
00751                  */
00752                 assert(b_false);
00753         case sc_prop:
00754                 stype_class_impl_check_prop(stype, cmbr_sym, if_tvv, ifmbr_sym);
00755                 break;
00756         }
00757 }
00758 
00766 static void stype_class_impl_check_fun(stype_t *stype,
00767     stree_symbol_t *cfun_sym, tdata_tvv_t *if_tvv, stree_symbol_t *ifun_sym)
00768 {
00769         stree_fun_t *cfun;
00770         tdata_fun_t *tcfun;
00771         stree_fun_t *ifun;
00772         tdata_item_t *sifun_ti;
00773         tdata_fun_t *tifun;
00774 
00775 #ifdef DEBUG_TYPE_TRACE
00776         printf("Verify that class '");
00777         symbol_print_fqn(csi_to_symbol(cfun_sym->outer_csi));
00778         printf("' implements function '");
00779         symbol_print_fqn(ifun_sym);
00780         printf("' properly.\n");
00781 #endif
00782         assert(cfun_sym->sc == sc_fun);
00783         cfun = cfun_sym->u.fun;
00784 
00785         assert(ifun_sym->sc == sc_fun);
00786         ifun = ifun_sym->u.fun;
00787 
00788         assert(cfun->titem->tic == tic_tfun);
00789         tcfun = cfun->titem->u.tfun;
00790 
00791         tdata_item_subst(ifun->titem, if_tvv, &sifun_ti);
00792         assert(sifun_ti->tic == tic_tfun);
00793         tifun = sifun_ti->u.tfun;
00794 
00795         if (!stype_fun_sig_equal(stype, tcfun->tsig, tifun->tsig)) {
00796                 cspan_print(cfun->name->cspan);
00797                 printf(" Error: Type of function '");
00798                 symbol_print_fqn(cfun_sym);
00799                 printf("' (");
00800                 tdata_item_print(cfun->titem);
00801                 printf(") does not match type of '");
00802                 symbol_print_fqn(ifun_sym);
00803                 printf("' (");
00804                 tdata_item_print(sifun_ti);
00805                 printf(") which it should implement.\n");
00806                 stype_note_error(stype);
00807         }
00808 }
00809 
00817 static void stype_class_impl_check_prop(stype_t *stype,
00818     stree_symbol_t *cprop_sym, tdata_tvv_t *if_tvv, stree_symbol_t *iprop_sym)
00819 {
00820         stree_prop_t *cprop;
00821         stree_prop_t *iprop;
00822         tdata_item_t *siprop_ti;
00823 
00824 #ifdef DEBUG_TYPE_TRACE
00825         printf("Verify that class '");
00826         symbol_print_fqn(csi_to_symbol(cprop_sym->outer_csi));
00827         printf("' implements property '");
00828         symbol_print_fqn(iprop_sym);
00829         printf("' properly.\n");
00830 #endif
00831         assert(cprop_sym->sc == sc_prop);
00832         cprop = cprop_sym->u.prop;
00833 
00834         assert(iprop_sym->sc == sc_prop);
00835         iprop = iprop_sym->u.prop;
00836 
00837         tdata_item_subst(iprop->titem, if_tvv, &siprop_ti);
00838 
00839         if (!tdata_item_equal(cprop->titem, siprop_ti)) {
00840                 cspan_print(cprop->name->cspan);
00841                 printf(" Error: Type of property '");
00842                 symbol_print_fqn(cprop_sym);
00843                 printf("' (");
00844                 tdata_item_print(cprop->titem);
00845                 printf(") does not match type of '");
00846                 symbol_print_fqn(iprop_sym);
00847                 printf("' (");
00848                 tdata_item_print(siprop_ti);
00849                 printf(") which it should implement.\n");
00850                 stype_note_error(stype);
00851         }
00852 
00853         if (iprop->getter != NULL && cprop->getter == NULL) {
00854                 cspan_print(cprop->name->cspan);
00855                 printf(" Error: Property '");
00856                 symbol_print_fqn(cprop_sym);
00857                 printf("' is missing a getter, which is required by '");
00858                 symbol_print_fqn(iprop_sym);
00859                 printf("'.\n");
00860                 stype_note_error(stype);
00861         }
00862 
00863         if (iprop->setter != NULL && cprop->setter == NULL) {
00864                 cspan_print(cprop->name->cspan);
00865                 printf(" Error: Property '");
00866                 symbol_print_fqn(cprop_sym);
00867                 printf("' is missing a setter, which is required by '");
00868                 symbol_print_fqn(iprop_sym);
00869                 printf("'.\n");
00870                 stype_note_error(stype);
00871         }
00872 }
00873 
00884 void stype_stat(stype_t *stype, stree_stat_t *stat, bool_t want_value)
00885 {
00886 #ifdef DEBUG_TYPE_TRACE
00887         printf("Type statement.\n");
00888 #endif
00889         switch (stat->sc) {
00890         case st_vdecl: stype_vdecl(stype, stat->u.vdecl_s); break;
00891         case st_if: stype_if(stype, stat->u.if_s); break;
00892         case st_switch: stype_switch(stype, stat->u.switch_s); break;
00893         case st_while: stype_while(stype, stat->u.while_s); break;
00894         case st_for: stype_for(stype, stat->u.for_s); break;
00895         case st_raise: stype_raise(stype, stat->u.raise_s); break;
00896         case st_break: stype_break(stype, stat->u.break_s); break;
00897         case st_return: stype_return(stype, stat->u.return_s); break;
00898         case st_exps: stype_exps(stype, stat->u.exp_s, want_value); break;
00899         case st_wef: stype_wef(stype, stat->u.wef_s); break;
00900         }
00901 }
00902 
00908 static void stype_vdecl(stype_t *stype, stree_vdecl_t *vdecl_s)
00909 {
00910         stype_block_vr_t *block_vr;
00911         stree_vdecl_t *old_vdecl;
00912         tdata_item_t *titem;
00913 
00914 #ifdef DEBUG_TYPE_TRACE
00915         printf("Type variable declaration statement.\n");
00916 #endif
00917         block_vr = stype_get_current_block_vr(stype);
00918         old_vdecl = (stree_vdecl_t *) intmap_get(&block_vr->vdecls,
00919             vdecl_s->name->sid);
00920 
00921         if (old_vdecl != NULL) {
00922                 printf("Error: Duplicate variable declaration '%s'.\n",
00923                     strtab_get_str(vdecl_s->name->sid));
00924                 stype_note_error(stype);
00925         }
00926 
00927         run_texpr(stype->program, stype->current_csi, vdecl_s->type,
00928             &titem);
00929         if (titem->tic == tic_ignore) {
00930                 /* An error occured. */
00931                 stype_note_error(stype);
00932                 return;
00933         }
00934 
00935         /* Annotate with variable type */
00936         vdecl_s->titem = titem;
00937 
00938         intmap_set(&block_vr->vdecls, vdecl_s->name->sid, vdecl_s);
00939 }
00940 
00946 static void stype_if(stype_t *stype, stree_if_t *if_s)
00947 {
00948         stree_expr_t *ccond;
00949         list_node_t *ifc_node;
00950         stree_if_clause_t *ifc;
00951 
00952 #ifdef DEBUG_TYPE_TRACE
00953         printf("Type 'if' statement.\n");
00954 #endif
00955         ifc_node = list_first(&if_s->if_clauses);
00956 
00957         /* Walk through all if/elif clauses. */
00958 
00959         while (ifc_node != NULL) {
00960                 /* Get if/elif clause */
00961                 ifc = list_node_data(ifc_node, stree_if_clause_t *);
00962 
00963                 /* Convert condition to boolean type. */
00964                 stype_expr(stype, ifc->cond);
00965                 ccond = stype_convert(stype, ifc->cond,
00966                     stype_boolean_titem(stype));
00967 
00968                 /* Patch code with augmented expression. */
00969                 ifc->cond = ccond;
00970 
00971                 /* Type the @c if/elif block */
00972                 stype_block(stype, ifc->block);
00973 
00974                 ifc_node = list_next(&if_s->if_clauses, ifc_node);
00975         }
00976 
00977         /* Type the @c else block */
00978         if (if_s->else_block != NULL)
00979                 stype_block(stype, if_s->else_block);
00980 }
00981 
00987 static void stype_switch(stype_t *stype, stree_switch_t *switch_s)
00988 {
00989         stree_expr_t *expr, *cexpr;
00990         list_node_t *whenc_node;
00991         stree_when_t *whenc;
00992         list_node_t *expr_node;
00993         tdata_item_t *titem1, *titem2;
00994 
00995 #ifdef DEBUG_TYPE_TRACE
00996         printf("Type 'switch' statement.\n");
00997 #endif
00998         stype_expr(stype, switch_s->expr);
00999 
01000         titem1 = switch_s->expr->titem;
01001         if (titem1 == NULL) {
01002                 cspan_print(switch_s->expr->cspan);
01003                 printf(" Error: Switch expression has no value.\n");
01004                 stype_note_error(stype);
01005                 return;
01006         }
01007 
01008         /* Walk through all when clauses. */
01009         whenc_node = list_first(&switch_s->when_clauses);
01010 
01011         while (whenc_node != NULL) {
01012                 /* Get when clause */
01013                 whenc = list_node_data(whenc_node, stree_when_t *);
01014 
01015                 /* Walk through all expressions of the when clause */
01016                 expr_node = list_first(&whenc->exprs);
01017                 while (expr_node != NULL) {
01018                         expr = list_node_data(expr_node, stree_expr_t *);
01019 
01020                         stype_expr(stype, expr);
01021                         titem2 = expr->titem;
01022                         if (titem2 == NULL) {
01023                                 cspan_print(expr->cspan);
01024                                 printf(" Error: When expression has no value.\n");
01025                                 stype_note_error(stype);
01026                                 return;
01027                         }
01028 
01029                         /* Convert expression to same type as switch expr. */
01030                         cexpr = stype_convert(stype, expr, titem1);
01031 
01032                         /* Patch code with augmented expression. */
01033                         list_node_setdata(expr_node, cexpr);
01034 
01035                         expr_node = list_next(&whenc->exprs, expr_node);
01036                 }
01037 
01038                 /* Type the @c when block */
01039                 stype_block(stype, whenc->block);
01040 
01041                 whenc_node = list_next(&switch_s->when_clauses, whenc_node);
01042         }
01043 
01044         /* Type the @c else block */
01045         if (switch_s->else_block != NULL)
01046                 stype_block(stype, switch_s->else_block);
01047 }
01048 
01054 static void stype_while(stype_t *stype, stree_while_t *while_s)
01055 {
01056         stree_expr_t *ccond;
01057 
01058 #ifdef DEBUG_TYPE_TRACE
01059         printf("Type 'while' statement.\n");
01060 #endif
01061         /* Convert condition to boolean type. */
01062         stype_expr(stype, while_s->cond);
01063         ccond = stype_convert(stype, while_s->cond,
01064             stype_boolean_titem(stype));
01065 
01066         /* Patch code with augmented expression. */
01067         while_s->cond = ccond;
01068 
01069         /* While is a breakable statement. Increment counter. */
01070         stype->proc_vr->bstat_cnt += 1;
01071 
01072         /* Type the body of the loop */
01073         stype_block(stype, while_s->body);
01074 
01075         stype->proc_vr->bstat_cnt -= 1;
01076 }
01077 
01083 static void stype_for(stype_t *stype, stree_for_t *for_s)
01084 {
01085 #ifdef DEBUG_TYPE_TRACE
01086         printf("Type 'for' statement.\n");
01087 #endif
01088         /* For is a breakable statement. Increment counter. */
01089         stype->proc_vr->bstat_cnt += 1;
01090 
01091         stype_block(stype, for_s->body);
01092 
01093         stype->proc_vr->bstat_cnt -= 1;
01094 }
01095 
01101 static void stype_raise(stype_t *stype, stree_raise_t *raise_s)
01102 {
01103 #ifdef DEBUG_TYPE_TRACE
01104         printf("Type 'raise' statement.\n");
01105 #endif
01106         stype_expr(stype, raise_s->expr);
01107 }
01108 
01110 static void stype_break(stype_t *stype, stree_break_t *break_s)
01111 {
01112 #ifdef DEBUG_TYPE_TRACE
01113         printf("Type 'break' statement.\n");
01114 #endif
01115         (void) break_s;
01116 
01117         /* Check whether there is an active statement to break from. */
01118         if (stype->proc_vr->bstat_cnt == 0) {
01119                 printf("Error: Break statement outside of while or for.\n");
01120                 stype_note_error(stype);
01121         }
01122 }
01123 
01125 static void stype_return(stype_t *stype, stree_return_t *return_s)
01126 {
01127         stree_symbol_t *outer_sym;
01128         stree_fun_t *fun;
01129         stree_prop_t *prop;
01130 
01131         stree_expr_t *cexpr;
01132         tdata_item_t *dtype;
01133 
01134 #ifdef DEBUG_TYPE_TRACE
01135         printf("Type 'return' statement.\n");
01136 #endif
01137         if (return_s->expr != NULL)
01138                 stype_expr(stype, return_s->expr);
01139 
01140         /* Determine the type we need to return. */
01141 
01142         outer_sym = stype->proc_vr->proc->outer_symbol;
01143         switch (outer_sym->sc) {
01144         case sc_fun:
01145                 fun = symbol_to_fun(outer_sym);
01146                 assert(fun != NULL);
01147 
01148                 /* XXX Memoize to avoid recomputing. */
01149                 if (fun->sig->rtype != NULL) {
01150                         run_texpr(stype->program, outer_sym->outer_csi,
01151                             fun->sig->rtype, &dtype);
01152 
01153                         if (return_s->expr == NULL) {
01154                                 printf("Error: Return without a value in "
01155                                     "function returning value.\n");
01156                                 stype_note_error(stype);
01157                         }
01158                 } else {
01159                         dtype = NULL;
01160 
01161                         if (return_s->expr != NULL) {
01162                                 printf("Error: Return with a value in "
01163                                     "value-less function.\n");
01164                                 stype_note_error(stype);
01165                         }
01166                 }
01167                 break;
01168         case sc_prop:
01169                 prop = symbol_to_prop(outer_sym);
01170                 assert(prop != NULL);
01171 
01172                 if (stype->proc_vr->proc == prop->getter) {
01173                         if (return_s->expr == NULL) {
01174                                 printf("Error: Return without a value in "
01175                                     "getter.\n");
01176                                 stype_note_error(stype);
01177                         }
01178                 } else {
01179                         if (return_s->expr == NULL) {
01180                                 printf("Error: Return with a value in "
01181                                     "setter.\n");
01182                                 stype_note_error(stype);
01183                         }
01184                 }
01185 
01186                 /* XXX Memoize to avoid recomputing. */
01187                 run_texpr(stype->program, outer_sym->outer_csi, prop->type,
01188                     &dtype);
01189                 break;
01190         default:
01191                 assert(b_false);
01192         }
01193 
01194         if (dtype != NULL && return_s->expr != NULL) {
01195                 /* Convert to the return type. */
01196                 cexpr = stype_convert(stype, return_s->expr, dtype);
01197 
01198                 /* Patch code with the augmented expression. */
01199                 return_s->expr = cexpr;
01200         }
01201 }
01202 
01208 static void stype_exps(stype_t *stype, stree_exps_t *exp_s, bool_t want_value)
01209 {
01210 #ifdef DEBUG_TYPE_TRACE
01211         printf("Type expression statement.\n");
01212 #endif
01213         stype_expr(stype, exp_s->expr);
01214 
01215         if (want_value == b_false && exp_s->expr->titem != NULL) {
01216                 cspan_print(exp_s->expr->cspan);
01217                 printf(" Warning: Expression value ignored.\n");
01218         }
01219 }
01220 
01226 static void stype_wef(stype_t *stype, stree_wef_t *wef_s)
01227 {
01228         list_node_t *ec_n;
01229         stree_except_t *ec;
01230 
01231 #ifdef DEBUG_TYPE_TRACE
01232         printf("Type WEF statement.\n");
01233 #endif
01234         /* Type the @c with block. */
01235         if (wef_s->with_block != NULL)
01236                 stype_block(stype, wef_s->with_block);
01237 
01238         /* Type the @c except clauses. */
01239         ec_n = list_first(&wef_s->except_clauses);
01240         while (ec_n != NULL) {
01241                 ec = list_node_data(ec_n, stree_except_t *);
01242                 run_texpr(stype->program, stype->current_csi, ec->etype,
01243                     &ec->titem);
01244                 stype_block(stype, ec->block);
01245 
01246                 ec_n = list_next(&wef_s->except_clauses, ec_n);
01247         }
01248 
01249         /* Type the @c finally block. */
01250         if (wef_s->finally_block != NULL)
01251                 stype_block(stype, wef_s->finally_block);
01252 }
01253 
01272 stree_expr_t *stype_convert(stype_t *stype, stree_expr_t *expr,
01273     tdata_item_t *dest)
01274 {
01275         tdata_item_t *src;
01276 
01277         src = expr->titem;
01278 
01279 #ifdef DEBUG_TYPE_TRACE
01280         printf("Convert '");
01281         tdata_item_print(src);
01282         printf("' to '");
01283         tdata_item_print(dest);
01284         printf("'.\n");
01285 #endif
01286 
01287         if (dest == NULL) {
01288                 printf("Error: Conversion destination is not valid.\n");
01289                 stype_note_error(stype);
01290                 return expr;
01291         }
01292 
01293         if (src == NULL) {
01294                 cspan_print(expr->cspan);
01295                 printf(" Error: Conversion source is not valid.\n");
01296                 stype_note_error(stype);
01297                 return expr;
01298         }
01299 
01300         if (dest->tic == tic_ignore || src->tic == tic_ignore)
01301                 return expr;
01302 
01303         /*
01304          * Special case: Nil to object.
01305          */
01306         if (src->tic == tic_tprimitive && src->u.tprimitive->tpc == tpc_nil) {
01307                 if (dest->tic == tic_tobject)
01308                         return expr;
01309         }
01310 
01311         if (src->tic == tic_tprimitive && dest->tic == tic_tobject) {
01312                 return stype_convert_tprim_tobj(stype, expr, dest);
01313         }
01314 
01315         if (src->tic == tic_tfun && dest->tic == tic_tdeleg) {
01316                 return stype_convert_tfun_tdeleg(stype, expr, dest);
01317         }
01318 
01319         if (src->tic == tic_tebase) {
01320                 stype_convert_failure(stype, convc_implicit, expr, dest);
01321                 printf("Invalid use of reference to enum type in "
01322                     "expression.\n");
01323                 return expr;
01324         }
01325 
01326         if (src->tic != dest->tic) {
01327                 stype_convert_failure(stype, convc_implicit, expr, dest);
01328                 return expr;
01329         }
01330 
01331         switch (src->tic) {
01332         case tic_tprimitive:
01333                 expr = stype_convert_tprimitive(stype, expr, dest);
01334                 break;
01335         case tic_tobject:
01336                 expr = stype_convert_tobject(stype, expr, dest);
01337                 break;
01338         case tic_tarray:
01339                 expr = stype_convert_tarray(stype, expr, dest);
01340                 break;
01341         case tic_tdeleg:
01342                 expr = stype_convert_tdeleg(stype, expr, dest);
01343                 break;
01344         case tic_tebase:
01345                 /* Conversion destination should never be enum-base */
01346                 assert(b_false);
01347         case tic_tenum:
01348                 expr = stype_convert_tenum(stype, expr, dest);
01349                 break;
01350         case tic_tfun:
01351                 assert(b_false);
01352         case tic_tvref:
01353                 expr = stype_convert_tvref(stype, expr, dest);
01354                 break;
01355         case tic_ignore:
01356                 assert(b_false);
01357         }
01358 
01359         return expr;
01360 }
01361 
01368 static stree_expr_t *stype_convert_tprimitive(stype_t *stype,
01369     stree_expr_t *expr, tdata_item_t *dest)
01370 {
01371         tdata_item_t *src;
01372 
01373 #ifdef DEBUG_TYPE_TRACE
01374         printf("Convert primitive type.\n");
01375 #endif
01376         src = expr->titem;
01377         assert(src->tic == tic_tprimitive);
01378         assert(dest->tic == tic_tprimitive);
01379 
01380         /* Check if both have the same tprimitive class. */
01381         if (src->u.tprimitive->tpc != dest->u.tprimitive->tpc)
01382                 stype_convert_failure(stype, convc_implicit, expr, dest);
01383 
01384         return expr;
01385 }
01386 
01396 static stree_expr_t *stype_convert_tprim_tobj(stype_t *stype,
01397     stree_expr_t *expr, tdata_item_t *dest)
01398 {
01399         tdata_item_t *src;
01400         builtin_t *bi;
01401         stree_symbol_t *csi_sym;
01402         stree_symbol_t *bp_sym;
01403         stree_box_t *box;
01404         stree_expr_t *bexpr;
01405 
01406 #ifdef DEBUG_TYPE_TRACE
01407         printf("Convert primitive type to object.\n");
01408 #endif
01409         src = expr->titem;
01410         assert(src->tic == tic_tprimitive);
01411         assert(dest->tic == tic_tobject);
01412 
01413         bi = stype->program->builtin;
01414         csi_sym = csi_to_symbol(dest->u.tobject->csi);
01415 
01416         /* Make compiler happy. */
01417         bp_sym = NULL;
01418 
01419         switch (src->u.tprimitive->tpc) {
01420         case tpc_bool: bp_sym = bi->boxed_bool; break;
01421         case tpc_char: bp_sym = bi->boxed_char; break;
01422         case tpc_int: bp_sym = bi->boxed_int; break;
01423         case tpc_nil: assert(b_false);
01424         case tpc_string: bp_sym = bi->boxed_string; break;
01425         case tpc_resource:
01426                 stype_convert_failure(stype, convc_implicit, expr, dest);
01427                 return expr;
01428         }
01429 
01430         /* Target type must be boxed @a src or Object */
01431         if (csi_sym != bp_sym && csi_sym != bi->gf_class)
01432                 stype_convert_failure(stype, convc_implicit, expr, dest);
01433 
01434         /* Patch the code to box the primitive value */
01435         box = stree_box_new();
01436         box->arg = expr;
01437         bexpr = stree_expr_new(ec_box);
01438         bexpr->u.box = box;
01439         bexpr->titem = dest;
01440 
01441         /* No action needed to optionally convert boxed type to Object */
01442 
01443         return bexpr;
01444 }
01445 
01452 static stree_expr_t *stype_convert_tobject(stype_t *stype, stree_expr_t *expr,
01453     tdata_item_t *dest)
01454 {
01455         tdata_item_t *src;
01456         tdata_item_t *pred_ti;
01457 
01458 #ifdef DEBUG_TYPE_TRACE
01459         printf("Convert object type.\n");
01460 #endif
01461         src = expr->titem;
01462         assert(src->tic == tic_tobject);
01463         assert(dest->tic == tic_tobject);
01464 
01465         /*
01466          * Find predecessor of the right type. This determines the
01467          * type arguments that the destination type should have.
01468          */
01469         pred_ti = stype_tobject_find_pred(stype, src, dest);
01470         if (pred_ti == NULL) {
01471                 stype_convert_failure(stype, convc_implicit, expr, dest);
01472                 printf("Not a base class or implemented or accumulated "
01473                     "interface.\n");
01474                 return expr;
01475         }
01476 
01477         /*
01478          * Verify that type arguments match with those specified for
01479          * conversion destination.
01480          */
01481         if (stype_targs_check_equal(stype, pred_ti, dest) != EOK) {
01482                 stype_convert_failure(stype, convc_implicit, expr, dest);
01483                 return expr;
01484         }
01485 
01486         return expr;
01487 }
01488 
01495 static stree_expr_t *stype_convert_tarray(stype_t *stype, stree_expr_t *expr,
01496     tdata_item_t *dest)
01497 {
01498         tdata_item_t *src;
01499 
01500 #ifdef DEBUG_TYPE_TRACE
01501         printf("Convert array type.\n");
01502 #endif
01503         src = expr->titem;
01504         assert(src->tic == tic_tarray);
01505         assert(dest->tic == tic_tarray);
01506 
01507         /* Compare rank and base type. */
01508         if (src->u.tarray->rank != dest->u.tarray->rank) {
01509                 stype_convert_failure(stype, convc_implicit, expr, dest);
01510                 return expr;
01511         }
01512 
01513         /* XXX Should we convert each element? */
01514         if (tdata_item_equal(src->u.tarray->base_ti,
01515             dest->u.tarray->base_ti) != b_true) {
01516                 stype_convert_failure(stype, convc_implicit, expr, dest);
01517         }
01518 
01519         return expr;
01520 }
01521 
01528 static stree_expr_t *stype_convert_tdeleg(stype_t *stype, stree_expr_t *expr,
01529     tdata_item_t *dest)
01530 {
01531         tdata_item_t *src;
01532         tdata_deleg_t *sdeleg, *ddeleg;
01533 
01534 #ifdef DEBUG_TYPE_TRACE
01535         printf("Convert delegate type.\n");
01536 #endif
01537         src = expr->titem;
01538         assert(src->tic == tic_tdeleg);
01539         assert(dest->tic == tic_tdeleg);
01540 
01541         sdeleg = src->u.tdeleg;
01542         ddeleg = dest->u.tdeleg;
01543 
01544         /*
01545          * XXX We need to redesign handling of generic types to handle
01546          * delegates in generic CSIs properly.
01547          */
01548 
01549         /* Destination should never be anonymous delegate. */
01550         assert(ddeleg->deleg != NULL);
01551 
01552         /* Both must be the same delegate. */
01553         if (sdeleg->deleg != ddeleg->deleg) {
01554                 stype_convert_failure(stype, convc_implicit, expr, dest);
01555                 return expr;
01556         }
01557 
01558         return expr;
01559 }
01560 
01567 static stree_expr_t *stype_convert_tenum(stype_t *stype, stree_expr_t *expr,
01568     tdata_item_t *dest)
01569 {
01570         tdata_item_t *src;
01571         tdata_enum_t *senum, *denum;
01572 
01573 #ifdef DEBUG_TYPE_TRACE
01574         printf("Convert enum type.\n");
01575 #endif
01576         src = expr->titem;
01577         assert(src->tic == tic_tenum);
01578         assert(dest->tic == tic_tenum);
01579 
01580         senum = src->u.tenum;
01581         denum = dest->u.tenum;
01582 
01583         /*
01584          * XXX How should enum types interact with generics?
01585          */
01586 
01587         /* Both must be of the same enum type (with the same declaration). */
01588         if (senum->enum_d != denum->enum_d) {
01589                 stype_convert_failure(stype, convc_implicit, expr, dest);
01590                 return expr;
01591         }
01592 
01593         return expr;
01594 }
01595 
01602 static stree_expr_t *stype_convert_tfun_tdeleg(stype_t *stype,
01603     stree_expr_t *expr, tdata_item_t *dest)
01604 {
01605         tdata_item_t *src;
01606         tdata_fun_t *sfun;
01607         tdata_deleg_t *ddeleg;
01608         tdata_fun_sig_t *ssig, *dsig;
01609 
01610 #ifdef DEBUG_TYPE_TRACE
01611         printf("Convert delegate type.\n");
01612 #endif
01613         src = expr->titem;
01614         assert(src->tic == tic_tfun);
01615         assert(dest->tic == tic_tdeleg);
01616 
01617         sfun = src->u.tfun;
01618         ddeleg = dest->u.tdeleg;
01619 
01620         ssig = sfun->tsig;
01621         assert(ssig != NULL);
01622         dsig = stype_deleg_get_sig(stype, ddeleg);
01623         assert(dsig != NULL);
01624 
01625         /* Signature type must match. */
01626 
01627         if (!stype_fun_sig_equal(stype, ssig, dsig)) {
01628                 stype_convert_failure(stype, convc_implicit, expr, dest);
01629                 return expr;
01630         }
01631 
01632         /*
01633          * XXX We should also compare attributes. Either the
01634          * tdeleg should be extended or we should get them
01635          * from stree_deleg.
01636          */
01637 
01638         return expr;
01639 }
01640 
01641 
01648 static stree_expr_t *stype_convert_tvref(stype_t *stype, stree_expr_t *expr,
01649     tdata_item_t *dest)
01650 {
01651         tdata_item_t *src;
01652 
01653 #ifdef DEBUG_TYPE_TRACE
01654         printf("Convert variable type.\n");
01655 #endif
01656         src = expr->titem;
01657 
01658         /* Currently only allow if both types are the same. */
01659         if (src->u.tvref->targ != dest->u.tvref->targ) {
01660                 stype_convert_failure(stype, convc_implicit, expr, dest);
01661                 return expr;
01662         }
01663 
01664         return expr;
01665 }
01666 
01673 void stype_convert_failure(stype_t *stype, stype_conv_class_t convc,
01674     stree_expr_t *expr, tdata_item_t *dest)
01675 {
01676         cspan_print(expr->cspan);
01677         printf(" Error: ");
01678         switch (convc) {
01679         case convc_implicit: printf("Cannot implicitly convert '"); break;
01680         case convc_as: printf("Cannot use 'as' to convert '"); break;
01681         }
01682 
01683         tdata_item_print(expr->titem);
01684         printf(" to ");
01685         tdata_item_print(dest);
01686         printf(".\n");
01687 
01688         stype_note_error(stype);
01689 }
01690 
01700 stree_expr_t *stype_box_expr(stype_t *stype, stree_expr_t *expr)
01701 {
01702         tdata_item_t *src;
01703         builtin_t *bi;
01704         stree_symbol_t *bp_sym;
01705         stree_box_t *box;
01706         stree_expr_t *bexpr;
01707         tdata_object_t *tobject;
01708 
01709 #ifdef DEBUG_TYPE_TRACE
01710         printf("Boxing.\n");
01711 #endif
01712         src = expr->titem;
01713         assert(src->tic == tic_tprimitive);
01714 
01715         bi = stype->program->builtin;
01716 
01717         /* Make compiler happy. */
01718         bp_sym = NULL;
01719 
01720         switch (src->u.tprimitive->tpc) {
01721         case tpc_bool: bp_sym = bi->boxed_bool; break;
01722         case tpc_char: bp_sym = bi->boxed_char; break;
01723         case tpc_int: bp_sym = bi->boxed_int; break;
01724         case tpc_nil: assert(b_false);
01725         case tpc_string: bp_sym = bi->boxed_string; break;
01726         case tpc_resource:
01727                 cspan_print(expr->cspan);
01728                 printf(" Error: Cannot use ");
01729                 tdata_item_print(expr->titem);
01730                 printf(" as an object.\n");
01731 
01732                 stype_note_error(stype);
01733                 return expr;
01734         }
01735 
01736         /* Patch the code to box the primitive value */
01737         box = stree_box_new();
01738         box->arg = expr;
01739         bexpr = stree_expr_new(ec_box);
01740         bexpr->u.box = box;
01741         bexpr->titem = tdata_item_new(tic_tobject);
01742         tobject = tdata_object_new();
01743         bexpr->titem->u.tobject = tobject;
01744 
01745         tobject->csi = symbol_to_csi(bp_sym);
01746         assert(tobject->csi != NULL);
01747 
01748         return bexpr;
01749 }
01750 
01763 tdata_item_t *stype_tobject_find_pred(stype_t *stype, tdata_item_t *src,
01764     tdata_item_t *dest)
01765 {
01766         stree_csi_t *src_csi;
01767         tdata_tvv_t *tvv;
01768         tdata_item_t *b_ti, *bs_ti;
01769 
01770         list_node_t *pred_n;
01771         stree_texpr_t *pred_te;
01772 
01773         tdata_item_t *res_ti;
01774 
01775 #ifdef DEBUG_TYPE_TRACE
01776         printf("Find CSI predecessor.\n");
01777 #endif
01778         assert(src->tic == tic_tobject);
01779         assert(dest->tic == tic_tobject);
01780 
01781         if (src->u.tobject->csi == dest->u.tobject->csi)
01782                 return src;
01783 
01784         src_csi = src->u.tobject->csi;
01785         stype_titem_to_tvv(stype, src, &tvv);
01786 
01787         res_ti = NULL;
01788 
01789         switch (dest->u.tobject->csi->cc) {
01790         case csi_class:
01791                 /* Destination is a class. Look at base class. */
01792                 pred_te = symbol_get_base_class_ref(stype->program,
01793                     src_csi);
01794                 if (pred_te != NULL) {
01795                         run_texpr(stype->program, src_csi, pred_te,
01796                             &b_ti);
01797                 } else if (src_csi->base_csi != NULL &&
01798                         src->u.tobject->csi->cc == csi_class) {
01799                         /* No explicit reference. Use grandfather class. */
01800                         b_ti = tdata_item_new(tic_tobject);
01801                         b_ti->u.tobject = tdata_object_new();
01802                         b_ti->u.tobject->csi = src_csi->base_csi;
01803                         b_ti->u.tobject->static_ref = sn_nonstatic;
01804 
01805                         list_init(&b_ti->u.tobject->targs);
01806                 } else {
01807                         /* No match */
01808                         return NULL;
01809                 }
01810 
01811                 /* Substitute type variables to get predecessor type. */
01812                 tdata_item_subst(b_ti, tvv, &bs_ti);
01813                 assert(bs_ti->tic == tic_tobject);
01814 
01815                 /* Recurse to compute the rest of the path. */
01816                 res_ti = stype_tobject_find_pred(stype, bs_ti, dest);
01817                 if (b_ti->tic == tic_ignore) {
01818                         /* An error occured. */
01819                         return NULL;
01820                 }
01821                 break;
01822         case csi_struct:
01823                 assert(b_false);
01824         case csi_interface:
01825                 /*
01826                  * Destination is an interface. Look at implemented
01827                  * or accumulated interfaces.
01828                  */
01829                 pred_n = list_first(&src_csi->inherit);
01830                 while (pred_n != NULL) {
01831                         pred_te = list_node_data(pred_n, stree_texpr_t *);
01832                         run_texpr(stype->program, src_csi, pred_te,
01833                             &b_ti);
01834 
01835                         /* Substitute type variables to get predecessor type. */
01836                         tdata_item_subst(b_ti, tvv, &bs_ti);
01837                         assert(bs_ti->tic == tic_tobject);
01838 
01839                         /* Recurse to compute the rest of the path. */
01840                         res_ti = stype_tobject_find_pred(stype, bs_ti, dest);
01841                         if (res_ti != NULL)
01842                                 break;
01843 
01844                         pred_n = list_next(&src_csi->inherit, pred_n);
01845                 }
01846                 break;
01847         }
01848 
01849         return res_ti;
01850 }
01851 
01866 int stype_targs_check_equal(stype_t *stype, tdata_item_t *a_ti,
01867     tdata_item_t *b_ti)
01868 {
01869         list_node_t *arg_a_n, *arg_b_n;
01870         tdata_item_t *arg_a, *arg_b;
01871 
01872         (void) stype;
01873 
01874 #ifdef DEBUG_TYPE_TRACE
01875         printf("Check if type arguments match.\n");
01876 #endif
01877         assert(a_ti->tic == tic_tobject);
01878         assert(b_ti->tic == tic_tobject);
01879 
01880         /*
01881          * Verify that type arguments match with those specified for
01882          * conversion b_tiination.
01883          */
01884         arg_a_n = list_first(&a_ti->u.tobject->targs);
01885         arg_b_n = list_first(&b_ti->u.tobject->targs);
01886 
01887         while (arg_a_n != NULL && arg_b_n != NULL) {
01888                 arg_a = list_node_data(arg_a_n, tdata_item_t *);
01889                 arg_b = list_node_data(arg_b_n, tdata_item_t *);
01890 
01891                 if (tdata_item_equal(arg_a, arg_b) != b_true) {
01892                         /* Diferent argument type */
01893                         printf("Different argument type '");
01894                         tdata_item_print(arg_a);
01895                         printf("' vs. '");
01896                         tdata_item_print(arg_b);
01897                         printf("'.\n");
01898                         return EINVAL;
01899                 }
01900 
01901                 arg_a_n = list_next(&a_ti->u.tobject->targs, arg_a_n);
01902                 arg_b_n = list_next(&b_ti->u.tobject->targs, arg_b_n);
01903         }
01904 
01905         if (arg_a_n != NULL || arg_b_n != NULL) {
01906                 /* Diferent number of arguments */
01907                 printf("Different number of arguments.\n");
01908                 return EINVAL;
01909         }
01910 
01911         return EOK;
01912 }
01913 
01914 
01924 static bool_t stype_fun_sig_equal(stype_t *stype, tdata_fun_sig_t *asig,
01925     tdata_fun_sig_t *bsig)
01926 {
01927         list_node_t *aarg_n, *barg_n;
01928         tdata_item_t *aarg_ti, *barg_ti;
01929 
01930         (void) stype;
01931 
01932         /* Compare types of arguments */
01933         aarg_n = list_first(&asig->arg_ti);
01934         barg_n = list_first(&bsig->arg_ti);
01935 
01936         while (aarg_n != NULL && barg_n != NULL) {
01937                 aarg_ti = list_node_data(aarg_n, tdata_item_t *);
01938                 barg_ti = list_node_data(barg_n, tdata_item_t *);
01939 
01940                 if (!tdata_item_equal(aarg_ti, barg_ti))
01941                         return b_false;
01942 
01943                 aarg_n = list_next(&asig->arg_ti, aarg_n);
01944                 barg_n = list_next(&bsig->arg_ti, barg_n);
01945         }
01946 
01947         if (aarg_n != NULL || barg_n != NULL)
01948                 return b_false;
01949 
01950         /* Compare variadic argument */
01951 
01952         if (asig->varg_ti != NULL || bsig->varg_ti != NULL) {
01953                 if (asig->varg_ti == NULL ||
01954                     bsig->varg_ti == NULL) {
01955                         return b_false;
01956                 }
01957 
01958                 if (!tdata_item_equal(asig->varg_ti, bsig->varg_ti)) {
01959                         return b_false;
01960                 }
01961         }
01962 
01963         /* Compare return type */
01964 
01965         if (asig->rtype != NULL || bsig->rtype != NULL) {
01966                 if (asig->rtype == NULL ||
01967                     bsig->rtype == NULL) {
01968                         return b_false;
01969                 }
01970 
01971                 if (!tdata_item_equal(asig->rtype, bsig->rtype)) {
01972                         return b_false;
01973                 }
01974         }
01975 
01976         return b_true;
01977 }
01978 
01985 tdata_fun_sig_t *stype_deleg_get_sig(stype_t *stype, tdata_deleg_t *tdeleg)
01986 {
01987         if (tdeleg->tsig == NULL)
01988                 stype_deleg(stype, tdeleg->deleg);
01989 
01990         /* Now we should have a signature. */
01991         assert(tdeleg->tsig != NULL);
01992         return tdeleg->tsig;
01993 }
01994 
02009 void stype_titem_to_tvv(stype_t *stype, tdata_item_t *ti, tdata_tvv_t **rtvv)
02010 {
02011         tdata_tvv_t *tvv;
02012         stree_csi_t *csi;
02013 
02014         list_node_t *formal_n;
02015         list_node_t *real_n;
02016 
02017         stree_targ_t *formal_arg;
02018         tdata_item_t *real_arg;
02019 
02020         assert(ti->tic == tic_tobject);
02021 
02022         tvv = tdata_tvv_new();
02023         intmap_init(&tvv->tvv);
02024 
02025         csi = ti->u.tobject->csi;
02026         formal_n = list_first(&csi->targ);
02027         real_n = list_first(&ti->u.tobject->targs);
02028 
02029         while (formal_n != NULL && real_n != NULL) {
02030                 formal_arg = list_node_data(formal_n, stree_targ_t *);
02031                 real_arg = list_node_data(real_n, tdata_item_t *);
02032 
02033                 /* Store argument value into valuation. */
02034                 tdata_tvv_set_val(tvv, formal_arg->name->sid, real_arg);
02035 
02036                 formal_n = list_next(&csi->targ, formal_n);
02037                 real_n = list_next(&ti->u.tobject->targs, real_n);
02038         }
02039 
02040         if (formal_n != NULL || real_n != NULL) {
02041                 printf("Error: Incorrect number of type arguments.\n");
02042                 stype_note_error(stype);
02043 
02044                 /* Fill missing arguments with recovery type items. */
02045                 while (formal_n != NULL) {
02046                         formal_arg = list_node_data(formal_n, stree_targ_t *);
02047                         /* Store recovery value into valuation. */
02048                         tdata_tvv_set_val(tvv, formal_arg->name->sid,
02049                             stype_recovery_titem(stype));
02050 
02051                         formal_n = list_next(&csi->targ, formal_n);
02052                 }
02053         }
02054 
02055         *rtvv = tvv;
02056 }
02057 
02063 tdata_item_t *stype_boolean_titem(stype_t *stype)
02064 {
02065         tdata_item_t *titem;
02066         tdata_primitive_t *tprimitive;
02067 
02068         (void) stype;
02069 
02070         titem = tdata_item_new(tic_tprimitive);
02071         tprimitive = tdata_primitive_new(tpc_bool);
02072         titem->u.tprimitive = tprimitive;
02073 
02074         return titem;
02075 }
02076 
02084 stree_vdecl_t *stype_local_vars_lookup(stype_t *stype, sid_t name)
02085 {
02086         stype_proc_vr_t *proc_vr;
02087         stype_block_vr_t *block_vr;
02088         stree_vdecl_t *vdecl;
02089         list_node_t *node;
02090 
02091         proc_vr = stype->proc_vr;
02092         node = list_last(&proc_vr->block_vr);
02093 
02094         /* Walk through all block visit records. */
02095         while (node != NULL) {
02096                 block_vr = list_node_data(node, stype_block_vr_t *);
02097                 vdecl = intmap_get(&block_vr->vdecls, name);
02098                 if (vdecl != NULL)
02099                         return vdecl;
02100 
02101                 node = list_prev(&proc_vr->block_vr, node);
02102         }
02103 
02104         /* No match */
02105         return NULL;
02106 }
02107 
02115 stree_proc_arg_t *stype_proc_args_lookup(stype_t *stype, sid_t name)
02116 {
02117         stype_proc_vr_t *proc_vr;
02118 
02119         stree_symbol_t *outer_sym;
02120         stree_ctor_t *ctor;
02121         stree_fun_t *fun;
02122         stree_prop_t *prop;
02123 
02124         list_t *args;
02125         list_node_t *arg_node;
02126         stree_proc_arg_t *varg;
02127         stree_proc_arg_t *arg;
02128         stree_proc_arg_t *setter_arg;
02129 
02130         proc_vr = stype->proc_vr;
02131         outer_sym = proc_vr->proc->outer_symbol;
02132 
02133         setter_arg = NULL;
02134 
02135 #ifdef DEBUG_TYPE_TRACE
02136         printf("Look for argument named '%s'.\n", strtab_get_str(name));
02137 #endif
02138 
02139         /* Make compiler happy. */
02140         args = NULL;
02141         varg = NULL;
02142 
02143         switch (outer_sym->sc) {
02144         case sc_ctor:
02145                 ctor = symbol_to_ctor(outer_sym);
02146                 assert(ctor != NULL);
02147                 args = &ctor->sig->args;
02148                 varg = ctor->sig->varg;
02149                 break;
02150         case sc_fun:
02151                 fun = symbol_to_fun(outer_sym);
02152                 assert(fun != NULL);
02153                 args = &fun->sig->args;
02154                 varg = fun->sig->varg;
02155                 break;
02156         case sc_prop:
02157                 prop = symbol_to_prop(outer_sym);
02158                 assert(prop != NULL);
02159                 args = &prop->args;
02160                 varg = prop->varg;
02161 
02162                 /* If we are in a setter, look also at setter argument. */
02163                 if (prop->setter == proc_vr->proc)
02164                         setter_arg = prop->setter_arg;
02165                 break;
02166         case sc_csi:
02167         case sc_deleg:
02168         case sc_enum:
02169         case sc_var:
02170                 assert(b_false);
02171         }
02172 
02173         arg_node = list_first(args);
02174         while (arg_node != NULL) {
02175                 arg = list_node_data(arg_node, stree_proc_arg_t *);
02176                 if (arg->name->sid == name) {
02177                         /* Match */
02178 #ifdef DEBUG_TYPE_TRACE
02179                         printf("Found argument.\n");
02180 #endif
02181                         return arg;
02182                 }
02183 
02184                 arg_node = list_next(args, arg_node);
02185         }
02186 
02187         /* Variadic argument */
02188         if (varg != NULL && varg->name->sid == name) {
02189 #ifdef DEBUG_TYPE_TRACE
02190                 printf("Found variadic argument.\n");
02191 #endif
02192                 return varg;
02193 }
02194 
02195         /* Setter argument */
02196         if (setter_arg != NULL && setter_arg->name->sid == name) {
02197 #ifdef DEBUG_TYPE_TRACE
02198                 printf("Found setter argument.\n");
02199 #endif
02200                 return setter_arg;
02201 
02202         }
02203 
02204 #ifdef DEBUG_TYPE_TRACE
02205         printf("Not found.\n");
02206 #endif
02207         /* No match */
02208         return NULL;
02209 }
02210 
02215 void stype_note_error(stype_t *stype)
02216 {
02217         stype->error = b_true;
02218 }
02219 
02227 tdata_item_t *stype_recovery_titem(stype_t *stype)
02228 {
02229         tdata_item_t *titem;
02230 
02231         (void) stype;
02232 
02233         titem = tdata_item_new(tic_ignore);
02234         return titem;
02235 }
02236 
02241 stype_block_vr_t *stype_get_current_block_vr(stype_t *stype)
02242 {
02243         list_node_t *node;
02244 
02245         node = list_last(&stype->proc_vr->block_vr);
02246         return list_node_data(node, stype_block_vr_t *);
02247 }
02248 
02253 stype_proc_vr_t *stype_proc_vr_new(void)
02254 {
02255         stype_proc_vr_t *proc_vr;
02256 
02257         proc_vr = calloc(1, sizeof(stype_proc_vr_t));
02258         if (proc_vr == NULL) {
02259                 printf("Memory allocation failed.\n");
02260                 exit(1);
02261         }
02262 
02263         return proc_vr;
02264 }
02265 
02270 stype_block_vr_t *stype_block_vr_new(void)
02271 {
02272         stype_block_vr_t *block_vr;
02273 
02274         block_vr = calloc(1, sizeof(stype_block_vr_t));
02275         if (block_vr == NULL) {
02276                 printf("Memory allocation failed.\n");
02277                 exit(1);
02278         }
02279 
02280         return block_vr;
02281 }

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7