stype_expr.c

00001 /*
00002  * Copyright (c) 2010 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 
00045 #include <stdio.h>
00046 #include <stdlib.h>
00047 #include <assert.h>
00048 #include "cspan.h"
00049 #include "debug.h"
00050 #include "list.h"
00051 #include "mytypes.h"
00052 #include "run_texpr.h"
00053 #include "stree.h"
00054 #include "strtab.h"
00055 #include "stype.h"
00056 #include "symbol.h"
00057 #include "tdata.h"
00058 
00059 #include "stype_expr.h"
00060 
00061 static void stype_nameref(stype_t *stype, stree_nameref_t *nameref,
00062     tdata_item_t **rtitem);
00063 static void stype_literal(stype_t *stype, stree_literal_t *literal,
00064     tdata_item_t **rtitem);
00065 static void stype_self_ref(stype_t *stype, stree_self_ref_t *self_ref,
00066     tdata_item_t **rtitem);
00067 
00068 static void stype_binop(stype_t *stype, stree_binop_t *binop,
00069     tdata_item_t **rtitem);
00070 
00071 static void stype_binop_tprimitive(stype_t *stype, stree_binop_t *binop,
00072     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem);
00073 static void stype_binop_bool(stype_t *stype, stree_binop_t *binop,
00074     tdata_item_t **rtitem);
00075 static void stype_binop_char(stype_t *stype, stree_binop_t *binop,
00076     tdata_item_t **rtitem);
00077 static void stype_binop_int(stype_t *stype, stree_binop_t *binop,
00078     tdata_item_t **rtitem);
00079 static void stype_binop_nil(stype_t *stype, stree_binop_t *binop,
00080     tdata_item_t **rtitem);
00081 static void stype_binop_string(stype_t *stype, stree_binop_t *binop,
00082     tdata_item_t **rtitem);
00083 static void stype_binop_resource(stype_t *stype, stree_binop_t *binop,
00084     tdata_item_t **rtitem);
00085 
00086 static void stype_binop_tobject(stype_t *stype, stree_binop_t *binop,
00087     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem);
00088 static void stype_binop_tenum(stype_t *stype, stree_binop_t *binop,
00089     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem);
00090 static void stype_binop_tvref(stype_t *stype, stree_binop_t *binop,
00091     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem);
00092 
00093 static void stype_unop(stype_t *stype, stree_unop_t *unop,
00094     tdata_item_t **rtitem);
00095 static void stype_unop_tprimitive(stype_t *stype, stree_unop_t *unop,
00096     tdata_item_t *ta, tdata_item_t **rtitem);
00097 static void stype_new(stype_t *stype, stree_new_t *new,
00098     tdata_item_t **rtitem);
00099 static void stype_new_object(stype_t *stype, stree_new_t *new_op,
00100     tdata_item_t *obj_ti);
00101 
00102 static void stype_access(stype_t *stype, stree_access_t *access,
00103     tdata_item_t **rtitem);
00104 static void stype_access_tprimitive(stype_t *stype, stree_access_t *access,
00105     tdata_item_t *arg_ti, tdata_item_t **rtitem);
00106 static void stype_access_tobject(stype_t *stype, stree_access_t *access,
00107     tdata_item_t *arg_ti, tdata_item_t **rtitem);
00108 static void stype_access_tarray(stype_t *stype, stree_access_t *access,
00109     tdata_item_t *arg_ti, tdata_item_t **rtitem);
00110 static void stype_access_tebase(stype_t *stype, stree_access_t *access,
00111     tdata_item_t *arg_ti, tdata_item_t **rtitem);
00112 
00113 static void stype_call(stype_t *stype, stree_call_t *call,
00114     tdata_item_t **rtitem);
00115 static void stype_call_args(stype_t *stype, cspan_t *cspan, list_t *farg_tis,
00116     tdata_item_t *fvarg_ti, list_t *args);
00117 
00118 static void stype_index(stype_t *stype, stree_index_t *index,
00119     tdata_item_t **rtitem);
00120 static void stype_index_tprimitive(stype_t *stype, stree_index_t *index,
00121     tdata_item_t *base_ti, tdata_item_t **rtitem);
00122 static void stype_index_tobject(stype_t *stype, stree_index_t *index,
00123     tdata_item_t *base_ti, tdata_item_t **rtitem);
00124 static void stype_index_tarray(stype_t *stype, stree_index_t *index,
00125     tdata_item_t *base_ti, tdata_item_t **rtitem);
00126 
00127 static void stype_assign(stype_t *stype, stree_assign_t *assign,
00128     tdata_item_t **rtitem);
00129 static void stype_as(stype_t *stype, stree_as_t *as_op, tdata_item_t **rtitem);
00130 static void stype_box(stype_t *stype, stree_box_t *box, tdata_item_t **rtitem);
00131 
00132 
00141 void stype_expr(stype_t *stype, stree_expr_t *expr)
00142 {
00143         tdata_item_t *et;
00144 
00145 #ifdef DEBUG_TYPE_TRACE
00146         cspan_print(expr->cspan);
00147         printf(" Type expression.\n");
00148 #endif
00149         /* Silence warning. */
00150         et = NULL;
00151 
00152         switch (expr->ec) {
00153         case ec_nameref: stype_nameref(stype, expr->u.nameref, &et); break;
00154         case ec_literal: stype_literal(stype, expr->u.literal, &et); break;
00155         case ec_self_ref: stype_self_ref(stype, expr->u.self_ref, &et); break;
00156         case ec_binop: stype_binop(stype, expr->u.binop, &et); break;
00157         case ec_unop: stype_unop(stype, expr->u.unop, &et); break;
00158         case ec_new: stype_new(stype, expr->u.new_op, &et); break;
00159         case ec_access: stype_access(stype, expr->u.access, &et); break;
00160         case ec_call: stype_call(stype, expr->u.call, &et); break;
00161         case ec_index: stype_index(stype, expr->u.index, &et); break;
00162         case ec_assign: stype_assign(stype, expr->u.assign, &et); break;
00163         case ec_as: stype_as(stype, expr->u.as_op, &et); break;
00164         case ec_box: stype_box(stype, expr->u.box, &et); break;
00165         }
00166 
00167         expr->titem = et;
00168 
00169 #ifdef DEBUG_TYPE_TRACE
00170         cspan_print(expr->cspan);
00171         printf(" Expression type is '");
00172         tdata_item_print(et);
00173         printf("'.\n");
00174 #endif
00175 }
00176 
00183 static void stype_nameref(stype_t *stype, stree_nameref_t *nameref,
00184     tdata_item_t **rtitem)
00185 {
00186         stree_symbol_t *sym;
00187         stree_vdecl_t *vdecl;
00188         stree_proc_arg_t *proc_arg;
00189         tdata_item_t *titem;
00190         tdata_object_t *tobject;
00191         stree_csi_t *csi;
00192         stree_deleg_t *deleg;
00193         stree_enum_t *enum_d;
00194         tdata_ebase_t *tebase;
00195         stree_fun_t *fun;
00196         bool_t static_ctx;
00197 
00198 #ifdef DEBUG_TYPE_TRACE
00199         cspan_print(nameref->expr->cspan);
00200         printf(" Evaluate type of name reference '%s'.\n",
00201             strtab_get_str(nameref->name->sid));
00202 #endif
00203         /*
00204          * Look for a local variable declaration.
00205          */
00206 
00207         vdecl = stype_local_vars_lookup(stype, nameref->name->sid);
00208         if (vdecl != NULL) {
00209                 /* Found a local variable declaration. */
00210 #ifdef DEBUG_RUN_TRACE
00211                 printf("Found local variable declaration.\n");
00212 #endif
00213                 run_texpr(stype->program, stype->current_csi, vdecl->type,
00214                     &titem);
00215                 *rtitem = titem;
00216                 return;
00217         }
00218 
00219         /*
00220          * Look for a procedure argument.
00221          */
00222 
00223         proc_arg = stype_proc_args_lookup(stype, nameref->name->sid);
00224         if (proc_arg != NULL) {
00225                 /* Found a procedure argument. */
00226 #ifdef DEBUG_RUN_TRACE
00227                 printf("Found procedure argument.\n");
00228 #endif
00229                 run_texpr(stype->program, stype->current_csi, proc_arg->type,
00230                     &titem);
00231                 *rtitem = titem;
00232                 return;
00233         }
00234 
00235         /*
00236          * Look for a class-wide or global symbol.
00237          */
00238 
00239         sym = symbol_lookup_in_csi(stype->program, stype->current_csi,
00240             nameref->name);
00241 
00242         if (sym == NULL) {
00243                 /* Not found. */
00244                 if (stype->current_csi != NULL) {
00245                         cspan_print(nameref->expr->cspan);
00246                         printf(" Error: Symbol '%s' not found in '",
00247                             strtab_get_str(nameref->name->sid));
00248                         symbol_print_fqn(csi_to_symbol(stype->current_csi));
00249                         printf("'.\n");
00250                 } else {
00251                         cspan_print(nameref->expr->cspan);
00252                         printf(" Error: Symbol '%s' not found.\n",
00253                             strtab_get_str(nameref->name->sid));
00254                 }
00255                 stype_note_error(stype);
00256                 *rtitem = stype_recovery_titem(stype);
00257                 return;
00258         }
00259 
00260         /* Determine if current procedure is static. */
00261         static_ctx = stree_symbol_is_static(stype->proc_vr->proc->outer_symbol);
00262 
00263         /*
00264          * If the symbol is not found in current CSI, then we access it
00265          * in a static context. (Context of current object cannot be used.)
00266          */
00267         if (sym->outer_csi != stype->current_csi)
00268                 static_ctx = b_true;
00269 
00270         /* Check for referencing non-static symbol in static context. */
00271         if (static_ctx && !stree_symbol_is_static(sym)) {
00272                 cspan_print(nameref->expr->cspan);
00273                 printf(" Error: Referencing non-static symbol '");
00274                 symbol_print_fqn(sym);
00275                 printf("' in static context.\n");
00276                 stype_note_error(stype);
00277                 *rtitem = stype_recovery_titem(stype);
00278                 return;
00279         }
00280 
00281         /* Referencing static member in non-static context is allowed. */
00282 
00283         /* Make compiler happy. */
00284         titem = NULL;
00285 
00286         switch (sym->sc) {
00287         case sc_var:
00288                 run_texpr(stype->program, stype->current_csi,
00289                     sym->u.var->type, &titem);
00290                 break;
00291         case sc_prop:
00292                 /* Type property header if it has not been typed yet. */
00293                 stype_prop_header(stype, sym->u.prop);
00294                 titem = sym->u.prop->titem;
00295                 break;
00296         case sc_csi:
00297                 csi = symbol_to_csi(sym);
00298                 assert(csi != NULL);
00299 
00300                 titem = tdata_item_new(tic_tobject);
00301                 tobject = tdata_object_new();
00302                 titem->u.tobject = tobject;
00303 
00304                 tobject->static_ref = sn_static;
00305                 tobject->csi = csi;
00306                 break;
00307         case sc_ctor:
00308                 /* It is not possible to reference a constructor explicitly. */
00309                 assert(b_false);
00310         case sc_deleg:
00311                 deleg = symbol_to_deleg(sym);
00312                 assert(deleg != NULL);
00313                 /* Type delegate if it has not been typed yet. */
00314                 stype_deleg(stype, deleg);
00315                 titem = deleg->titem;
00316                 break;
00317         case sc_enum:
00318                 enum_d = symbol_to_enum(sym);
00319                 assert(enum_d != NULL);
00320 
00321                 titem = tdata_item_new(tic_tebase);
00322                 tebase = tdata_ebase_new();
00323                 titem->u.tebase = tebase;
00324 
00325                 /* This is an enum base reference. */
00326                 tebase->enum_d = enum_d;
00327                 break;
00328         case sc_fun:
00329                 fun = symbol_to_fun(sym);
00330                 assert(fun != NULL);
00331                 /* Type function header if it has not been typed yet. */
00332                 stype_fun_header(stype, fun);
00333                 titem = fun->titem;
00334                 break;
00335         }
00336 
00337         *rtitem = titem;
00338 }
00339 
00346 static void stype_literal(stype_t *stype, stree_literal_t *literal,
00347     tdata_item_t **rtitem)
00348 {
00349         tdata_item_t *titem;
00350         tdata_primitive_t *tprimitive;
00351         tprimitive_class_t tpc;
00352 
00353 #ifdef DEBUG_TYPE_TRACE
00354         cspan_print(literal->expr->cspan);
00355         printf(" Evaluate type of literal.\n");
00356 #endif
00357         (void) stype;
00358 
00359         /* Make compiler happy. */
00360         tpc = 0;
00361 
00362         switch (literal->ltc) {
00363         case ltc_bool: tpc = tpc_bool; break;
00364         case ltc_char: tpc = tpc_char; break;
00365         case ltc_int: tpc = tpc_int; break;
00366         case ltc_ref: tpc = tpc_nil; break;
00367         case ltc_string: tpc = tpc_string; break;
00368         }
00369 
00370         titem = tdata_item_new(tic_tprimitive);
00371         tprimitive = tdata_primitive_new(tpc);
00372         titem->u.tprimitive = tprimitive;
00373 
00374         *rtitem = titem;
00375 }
00376 
00383 static void stype_self_ref(stype_t *stype, stree_self_ref_t *self_ref,
00384     tdata_item_t **rtitem)
00385 {
00386         stree_csi_t *cur_csi;
00387         tdata_item_t *titem;
00388         tdata_object_t *tobject;
00389 
00390 #ifdef DEBUG_TYPE_TRACE
00391         cspan_print(self_ref->expr->cspan);
00392         printf(" Evaluate type of self reference.\n");
00393 #endif
00394         (void) stype;
00395         (void) self_ref;
00396 
00397         cur_csi = stype->proc_vr->proc->outer_symbol->outer_csi;
00398 
00399         /* No global symbols should have procedures. */
00400         assert(cur_csi != NULL);
00401 
00402         /* Construct type item. */
00403         titem = tdata_item_new(tic_tobject);
00404         tobject = tdata_object_new();
00405         titem->u.tobject = tobject;
00406 
00407         tobject->static_ref = sn_nonstatic;
00408         tobject->csi = cur_csi;
00409         list_init(&tobject->targs);
00410 
00411         *rtitem = titem;
00412 }
00413 
00420 static void stype_binop(stype_t *stype, stree_binop_t *binop,
00421     tdata_item_t **rtitem)
00422 {
00423         bool_t equal;
00424         tdata_item_t *titem1, *titem2;
00425 
00426 #ifdef DEBUG_TYPE_TRACE
00427         cspan_print(binop->expr->cspan);
00428         printf(" Evaluate type of binary operation.\n");
00429 #endif
00430         stype_expr(stype, binop->arg1);
00431         stype_expr(stype, binop->arg2);
00432 
00433         titem1 = binop->arg1->titem;
00434         titem2 = binop->arg2->titem;
00435 
00436         if (titem1 == NULL) {
00437                 cspan_print(binop->arg1->cspan);
00438                 printf(" Error: Binary operand has no value.\n");
00439                 stype_note_error(stype);
00440                 *rtitem = stype_recovery_titem(stype);
00441                 return;
00442         }
00443 
00444         if (titem2 == NULL) {
00445                 cspan_print(binop->arg2->cspan);
00446                 printf(" Error: Binary operand has no value.\n");
00447                 stype_note_error(stype);
00448                 *rtitem = stype_recovery_titem(stype);
00449                 return;
00450         }
00451 
00452         if (titem1->tic == tic_ignore || titem2->tic == tic_ignore) {
00453                 *rtitem = stype_recovery_titem(stype);
00454                 return;
00455         }
00456 
00457         equal = tdata_item_equal(titem1, titem2);
00458         if (equal != b_true) {
00459                 cspan_print(binop->expr->cspan);
00460                 printf(" Error: Binary operation arguments "
00461                     "have different types ('");
00462                 tdata_item_print(titem1);
00463                 printf("' and '");
00464                 tdata_item_print(titem2);
00465                 printf("').\n");
00466                 stype_note_error(stype);
00467                 *rtitem = stype_recovery_titem(stype);
00468                 return;
00469         }
00470 
00471         switch (titem1->tic) {
00472         case tic_tprimitive:
00473                 stype_binop_tprimitive(stype, binop, titem1, titem2, rtitem);
00474                 break;
00475         case tic_tobject:
00476                 stype_binop_tobject(stype, binop, titem1, titem2, rtitem);
00477                 break;
00478         case tic_tenum:
00479                 stype_binop_tenum(stype, binop, titem1, titem2, rtitem);
00480                 break;
00481         case tic_tvref:
00482                 stype_binop_tvref(stype, binop, titem1, titem2, rtitem);
00483                 break;
00484         default:
00485                 cspan_print(binop->expr->cspan);
00486                 printf(" Error: Binary operation on value which is not of a "
00487                     "supported type (found '");
00488                 tdata_item_print(titem1);
00489                 printf("').\n");
00490                 stype_note_error(stype);
00491                 *rtitem = stype_recovery_titem(stype);
00492                 break;
00493         }
00494 
00495 }
00496 
00505 static void stype_binop_tprimitive(stype_t *stype, stree_binop_t *binop,
00506     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem)
00507 {
00508         assert(ta->tic == tic_tprimitive);
00509         assert(tb->tic == tic_tprimitive);
00510 
00511         switch (ta->u.tprimitive->tpc) {
00512         case tpc_bool:
00513                 stype_binop_bool(stype, binop, rtitem);
00514                 break;
00515         case tpc_char:
00516                 stype_binop_char(stype, binop, rtitem);
00517                 break;
00518         case tpc_int:
00519                 stype_binop_int(stype, binop, rtitem);
00520                 break;
00521         case tpc_nil:
00522                 stype_binop_nil(stype, binop, rtitem);
00523                 break;
00524         case tpc_string:
00525                 stype_binop_string(stype, binop, rtitem);
00526                 break;
00527         case tpc_resource:
00528                 stype_binop_resource(stype, binop, rtitem);
00529                 break;
00530         }
00531 }
00532 
00539 static void stype_binop_bool(stype_t *stype, stree_binop_t *binop,
00540     tdata_item_t **rtitem)
00541 {
00542         tprimitive_class_t rtpc;
00543         tdata_item_t *res_ti;
00544 
00545         /* Make compiler happy. */
00546         rtpc = 0;
00547 
00548         switch (binop->bc) {
00549         case bo_equal:
00550         case bo_notequal:
00551         case bo_lt:
00552         case bo_gt:
00553         case bo_lt_equal:
00554         case bo_gt_equal:
00555                 /* Comparison -> boolean type */
00556                 rtpc = tpc_bool;
00557                 break;
00558         case bo_plus:
00559         case bo_minus:
00560         case bo_mult:
00561                 /* Arithmetic -> error */
00562                 cspan_print(binop->expr->cspan);
00563                 printf(" Error: Binary operation (%d) on booleans.\n",
00564                     binop->bc);
00565                 stype_note_error(stype);
00566                 *rtitem = stype_recovery_titem(stype);
00567                 return;
00568         case bo_and:
00569         case bo_or:
00570                 /* Boolean -> boolean type */
00571                 rtpc = tpc_bool;
00572                 break;
00573         }
00574 
00575         res_ti = tdata_item_new(tic_tprimitive);
00576         res_ti->u.tprimitive = tdata_primitive_new(rtpc);
00577 
00578         *rtitem = res_ti;
00579 }
00580 
00587 static void stype_binop_char(stype_t *stype, stree_binop_t *binop,
00588     tdata_item_t **rtitem)
00589 {
00590         tprimitive_class_t rtpc;
00591         tdata_item_t *res_ti;
00592 
00593         (void) stype;
00594 
00595         /* Make compiler happy. */
00596         rtpc = 0;
00597 
00598         switch (binop->bc) {
00599         case bo_equal:
00600         case bo_notequal:
00601         case bo_lt:
00602         case bo_gt:
00603         case bo_lt_equal:
00604         case bo_gt_equal:
00605                 /* Comparison -> boolean type */
00606                 rtpc = tpc_bool;
00607                 break;
00608         case bo_plus:
00609         case bo_minus:
00610         case bo_mult:
00611         case bo_and:
00612         case bo_or:
00613                 /* Arithmetic, boolean -> error */
00614                 cspan_print(binop->expr->cspan);
00615                 printf(" Error: Binary operation (%d) on characters.\n",
00616                     binop->bc);
00617                 stype_note_error(stype);
00618                 rtpc = tpc_char;
00619                 break;
00620         }
00621 
00622         res_ti = tdata_item_new(tic_tprimitive);
00623         res_ti->u.tprimitive = tdata_primitive_new(rtpc);
00624 
00625         *rtitem = res_ti;
00626 }
00627 
00634 static void stype_binop_int(stype_t *stype, stree_binop_t *binop,
00635     tdata_item_t **rtitem)
00636 {
00637         tprimitive_class_t rtpc;
00638         tdata_item_t *res_ti;
00639 
00640         (void) stype;
00641 
00642         /* Make compiler happy. */
00643         rtpc = 0;
00644 
00645         switch (binop->bc) {
00646         case bo_equal:
00647         case bo_notequal:
00648         case bo_lt:
00649         case bo_gt:
00650         case bo_lt_equal:
00651         case bo_gt_equal:
00652                 /* Comparison -> boolean type */
00653                 rtpc = tpc_bool;
00654                 break;
00655         case bo_plus:
00656         case bo_minus:
00657         case bo_mult:
00658                 /* Arithmetic -> int type */
00659                 rtpc = tpc_int;
00660                 break;
00661         case bo_and:
00662         case bo_or:
00663                 /* Boolean -> error */
00664                 cspan_print(binop->expr->cspan);
00665                 printf(" Error: Binary operation (%d) on integers.\n",
00666                     binop->bc);
00667                 stype_note_error(stype);
00668                 rtpc = tpc_char;
00669                 break;
00670         }
00671 
00672         res_ti = tdata_item_new(tic_tprimitive);
00673         res_ti->u.tprimitive = tdata_primitive_new(rtpc);
00674 
00675         *rtitem = res_ti;
00676 }
00677 
00684 static void stype_binop_nil(stype_t *stype, stree_binop_t *binop,
00685     tdata_item_t **rtitem)
00686 {
00687         (void) binop;
00688 
00689         cspan_print(binop->expr->cspan);
00690         printf(" Unimplemented: Binary operation on nil.\n");
00691         stype_note_error(stype);
00692         *rtitem = stype_recovery_titem(stype);
00693 }
00694 
00701 static void stype_binop_string(stype_t *stype, stree_binop_t *binop,
00702     tdata_item_t **rtitem)
00703 {
00704         tprimitive_class_t rtpc;
00705         tdata_item_t *res_ti;
00706 
00707         /* Make compiler happy. */
00708         rtpc = 0;
00709 
00710         switch (binop->bc) {
00711         case bo_equal:
00712         case bo_notequal:
00713                 /* Comparison -> boolean type */
00714                 rtpc = tpc_bool;
00715                 break;
00716         case bo_plus:
00717                 /* Concatenation -> string type */
00718                 rtpc = tpc_string;
00719                 break;
00720 
00721         case bo_lt:
00722         case bo_gt:
00723         case bo_lt_equal:
00724         case bo_gt_equal:
00725 
00726         case bo_minus:
00727         case bo_mult:
00728         case bo_and:
00729         case bo_or:
00730                 /* Ordering, arithmetic, boolean -> error */
00731                 cspan_print(binop->expr->cspan);
00732                 printf(" Error: Binary operation (%d) on strings.\n",
00733                     binop->bc);
00734                 stype_note_error(stype);
00735                 rtpc = tpc_char;
00736                 break;
00737         }
00738 
00739         res_ti = tdata_item_new(tic_tprimitive);
00740         res_ti->u.tprimitive = tdata_primitive_new(rtpc);
00741 
00742         *rtitem = res_ti;
00743 }
00744 
00751 static void stype_binop_resource(stype_t *stype, stree_binop_t *binop,
00752     tdata_item_t **rtitem)
00753 {
00754         tprimitive_class_t rtpc;
00755         tdata_item_t *res_ti;
00756 
00757         (void) binop;
00758 
00759         cspan_print(binop->expr->cspan);
00760         printf(" Error: Cannot apply operator to resource type.\n");
00761         stype_note_error(stype);
00762         rtpc = tpc_resource;
00763 
00764         res_ti = tdata_item_new(tic_tprimitive);
00765         res_ti->u.tprimitive = tdata_primitive_new(rtpc);
00766 
00767         *rtitem = res_ti;
00768 }
00769 
00778 static void stype_binop_tobject(stype_t *stype, stree_binop_t *binop,
00779     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem)
00780 {
00781         tdata_item_t *res_ti;
00782 
00783         (void) stype;
00784 
00785         assert(ta->tic == tic_tobject || (ta->tic == tic_tprimitive &&
00786             ta->u.tprimitive->tpc == tpc_nil));
00787         assert(tb->tic == tic_tobject || (tb->tic == tic_tprimitive &&
00788             tb->u.tprimitive->tpc == tpc_nil));
00789 
00790         switch (binop->bc) {
00791         case bo_equal:
00792         case bo_notequal:
00793                 /* Comparing objects -> boolean type */
00794                 res_ti = stype_boolean_titem(stype);
00795                 break;
00796         default:
00797                 cspan_print(binop->expr->cspan);
00798                 printf(" Error: Binary operation (%d) on objects.\n",
00799                     binop->bc);
00800                 stype_note_error(stype);
00801                 *rtitem = stype_recovery_titem(stype);
00802                 return;
00803         }
00804 
00805         *rtitem = res_ti;
00806 }
00807 
00816 static void stype_binop_tenum(stype_t *stype, stree_binop_t *binop,
00817     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem)
00818 {
00819         tdata_item_t *res_ti;
00820 
00821         assert(ta->tic == tic_tenum);
00822         assert(tb->tic == tic_tenum);
00823 
00824         switch (binop->bc) {
00825         case bo_equal:
00826         case bo_notequal:
00827                 /* Comparison -> boolean type */
00828                 res_ti = stype_boolean_titem(stype);
00829                 break;
00830         default:
00831                 cspan_print(binop->expr->cspan);
00832                 printf(" Error: Binary operation (%d) on values of enum "
00833                     "type.\n", binop->bc);
00834                 stype_note_error(stype);
00835                 *rtitem = stype_recovery_titem(stype);
00836                 return;
00837         }
00838 
00839         *rtitem = res_ti;
00840 }
00841 
00850 static void stype_binop_tvref(stype_t *stype, stree_binop_t *binop,
00851     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem)
00852 {
00853         tdata_item_t *res_ti;
00854 
00855         assert(ta->tic == tic_tvref || (ta->tic == tic_tprimitive &&
00856             ta->u.tprimitive->tpc == tpc_nil));
00857         assert(tb->tic == tic_tvref || (tb->tic == tic_tprimitive &&
00858             tb->u.tprimitive->tpc == tpc_nil));
00859 
00860         switch (binop->bc) {
00861         case bo_equal:
00862         case bo_notequal:
00863                 /* Comparison -> boolean type */
00864                 res_ti = stype_boolean_titem(stype);
00865                 break;
00866         default:
00867                 cspan_print(binop->expr->cspan);
00868                 printf(" Error: Binary operation (%d) on variable types.\n",
00869                     binop->bc);
00870                 stype_note_error(stype);
00871                 *rtitem = stype_recovery_titem(stype);
00872                 return;
00873         }
00874 
00875         *rtitem = res_ti;
00876 }
00877 
00884 static void stype_unop(stype_t *stype, stree_unop_t *unop,
00885     tdata_item_t **rtitem)
00886 {
00887         tdata_item_t *titem;
00888 
00889 #ifdef DEBUG_TYPE_TRACE
00890         cspan_print(unop->expr->cspan);
00891         printf(" Evaluate type of unary operation.\n");
00892 #endif
00893         stype_expr(stype, unop->arg);
00894 
00895         titem = unop->arg->titem;
00896         if (titem == NULL) {
00897                 cspan_print(unop->arg->cspan);
00898                 printf(" Error: Argument of unary operation has no value.\n");
00899                 stype_note_error(stype);
00900                 *rtitem = stype_recovery_titem(stype);
00901                 return;
00902         }
00903 
00904         if (titem->tic == tic_ignore) {
00905                 *rtitem = stype_recovery_titem(stype);
00906                 return;
00907         }
00908 
00909         switch (titem->tic) {
00910         case tic_tprimitive:
00911                 stype_unop_tprimitive(stype, unop, titem, rtitem);
00912                 break;
00913         default:
00914                 cspan_print(unop->arg->cspan);
00915                 printf(" Error: Unary operation on value which is not of a "
00916                     "supported type (found '");
00917                 tdata_item_print(titem);
00918                 printf("').\n");
00919                 stype_note_error(stype);
00920                 *rtitem = stype_recovery_titem(stype);
00921                 break;
00922         }
00923 }
00924 
00932 static void stype_unop_tprimitive(stype_t *stype, stree_unop_t *unop,
00933     tdata_item_t *ta, tdata_item_t **rtitem)
00934 {
00935         tprimitive_class_t rtpc;
00936         tdata_item_t *res_ti;
00937 
00938         (void) stype;
00939         (void) unop;
00940 
00941         assert(ta->tic == tic_tprimitive);
00942 
00943         switch (ta->u.tprimitive->tpc) {
00944         case tpc_bool:
00945                 rtpc = tpc_bool;
00946                 break;
00947         case tpc_int:
00948                 rtpc = tpc_int;
00949                 break;
00950         default:
00951                 cspan_print(unop->arg->cspan);
00952                 printf(" Error: Unary operator applied on unsupported "
00953                     "primitive type %d.\n", ta->u.tprimitive->tpc);
00954                 stype_note_error(stype);
00955                 *rtitem = stype_recovery_titem(stype);
00956                 return;
00957         }
00958 
00959         res_ti = tdata_item_new(tic_tprimitive);
00960         res_ti->u.tprimitive = tdata_primitive_new(rtpc);
00961 
00962         *rtitem = res_ti;
00963 }
00964 
00971 static void stype_new(stype_t *stype, stree_new_t *new_op,
00972     tdata_item_t **rtitem)
00973 {
00974 #ifdef DEBUG_TYPE_TRACE
00975         cspan_print(new_op->expr->cspan);
00976         printf("Evaluate type of 'new' operation.\n");
00977 #endif
00978         /*
00979          * Type of @c new expression is exactly the type supplied as parameter
00980          * to the @c new operator.
00981          */
00982         run_texpr(stype->program, stype->current_csi, new_op->texpr, rtitem);
00983 
00984         if ((*rtitem)->tic == tic_ignore) {
00985                 /* An error occured when evaluating the type expression. */
00986                 stype_note_error(stype);
00987                 *rtitem = stype_recovery_titem(stype);
00988                 return;
00989         }
00990 
00991         if ((*rtitem)->tic == tic_tobject)
00992                 stype_new_object(stype, new_op, *rtitem);
00993 }
00994 
01000 static void stype_new_object(stype_t *stype, stree_new_t *new_op,
01001     tdata_item_t *obj_ti)
01002 {
01003         stree_csi_t *csi;
01004         stree_ctor_t *ctor;
01005         stree_symbol_t *ctor_sym;
01006         stree_ident_t *ctor_ident;
01007         tdata_fun_sig_t *tsig;
01008         tdata_tvv_t *obj_tvv;
01009         tdata_item_t *ctor_sti;
01010 
01011         assert(obj_ti->tic == tic_tobject);
01012         csi = obj_ti->u.tobject->csi;
01013 
01014         if (csi->cc == csi_interface) {
01015                 cspan_print(new_op->expr->cspan);
01016                 printf(" Error: Cannot instantiate an interface.\n");
01017                 stype_note_error(stype);
01018                 return;
01019         }
01020 
01021         ctor_ident = stree_ident_new();
01022         ctor_ident->sid = strtab_get_sid(CTOR_IDENT);
01023 
01024         /* Find constructor. */
01025         ctor_sym = symbol_search_csi_no_base(stype->program, csi,
01026             ctor_ident);
01027 
01028         if (ctor_sym == NULL && !list_is_empty(&new_op->ctor_args)) {
01029                 cspan_print(new_op->expr->cspan);
01030                 printf(" Error: Passing arguments to 'new' but no "
01031                     "constructor found.\n");
01032                 stype_note_error(stype);
01033                 return;
01034         }
01035 
01036         if (ctor_sym == NULL)
01037                 return;
01038 
01039         ctor = symbol_to_ctor(ctor_sym);
01040         assert(ctor != NULL);
01041 
01042         /* Type constructor header if it has not been typed yet. */
01043         stype_ctor_header(stype, ctor);
01044         if (ctor->titem->tic == tic_ignore)
01045                 return;
01046 
01047         /* Substitute type arguments in constructor type. */
01048         stype_titem_to_tvv(stype, obj_ti, &obj_tvv);
01049         tdata_item_subst(ctor->titem, obj_tvv, &ctor_sti);
01050         /* XXX Free obj_tvv */
01051 
01052         assert(ctor_sti->tic == tic_tfun);
01053         tsig = ctor_sti->u.tfun->tsig;
01054 
01055         stype_call_args(stype, new_op->expr->cspan, &tsig->arg_ti,
01056             tsig->varg_ti, &new_op->ctor_args);
01057 }
01058 
01065 static void stype_access(stype_t *stype, stree_access_t *access,
01066     tdata_item_t **rtitem)
01067 {
01068         tdata_item_t *arg_ti;
01069 
01070 #ifdef DEBUG_TYPE_TRACE
01071         cspan_print(access->expr->cspan);
01072         printf(" Evaluate type of access operation.\n");
01073 #endif
01074         stype_expr(stype, access->arg);
01075         arg_ti = access->arg->titem;
01076 
01077         if (arg_ti == NULL) {
01078                 cspan_print(access->arg->cspan);
01079                 printf(" Error: Argument of access operation has no value.\n");
01080                 stype_note_error(stype);
01081                 *rtitem = stype_recovery_titem(stype);
01082                 return;
01083         }
01084 
01085         switch (arg_ti->tic) {
01086         case tic_tprimitive:
01087                 stype_access_tprimitive(stype, access, arg_ti, rtitem);
01088                 break;
01089         case tic_tobject:
01090                 stype_access_tobject(stype, access, arg_ti, rtitem);
01091                 break;
01092         case tic_tarray:
01093                 stype_access_tarray(stype, access, arg_ti, rtitem);
01094                 break;
01095         case tic_tdeleg:
01096                 cspan_print(access->arg->cspan);
01097                 printf(" Error: Using '.' operator on a delegate.\n");
01098                 stype_note_error(stype);
01099                 *rtitem = stype_recovery_titem(stype);
01100                 break;
01101         case tic_tebase:
01102                 stype_access_tebase(stype, access, arg_ti, rtitem);
01103                 break;
01104         case tic_tenum:
01105                 cspan_print(access->arg->cspan);
01106                 printf(" Error: Using '.' operator on expression of enum "
01107                     "type.\n");
01108                 stype_note_error(stype);
01109                 *rtitem = stype_recovery_titem(stype);
01110                 break;
01111         case tic_tfun:
01112                 cspan_print(access->arg->cspan);
01113                 printf(" Error: Using '.' operator on a function.\n");
01114                 stype_note_error(stype);
01115                 *rtitem = stype_recovery_titem(stype);
01116                 break;
01117         case tic_tvref:
01118                 /* Cannot allow this without some constraint. */
01119                 cspan_print(access->arg->cspan);
01120                 printf(" Error: Using '.' operator on generic data.\n");
01121                 *rtitem = stype_recovery_titem(stype);
01122                 break;
01123         case tic_ignore:
01124                 *rtitem = stype_recovery_titem(stype);
01125                 break;
01126         }
01127 }
01128 
01136 static void stype_access_tprimitive(stype_t *stype, stree_access_t *access,
01137     tdata_item_t *arg_ti, tdata_item_t **rtitem)
01138 {
01139         (void) arg_ti;
01140 
01141         /* Box the value. */
01142         access->arg = stype_box_expr(stype, access->arg);
01143         if (access->arg->titem->tic == tic_ignore) {
01144                 *rtitem = stype_recovery_titem(stype);
01145                 return;
01146         }
01147 
01148         /* Access the boxed object. */
01149         stype_access_tobject(stype, access, access->arg->titem, rtitem);
01150 }
01151 
01159 static void stype_access_tobject(stype_t *stype, stree_access_t *access,
01160     tdata_item_t *arg_ti, tdata_item_t **rtitem)
01161 {
01162         stree_symbol_t *member_sym;
01163         stree_var_t *var;
01164         stree_enum_t *enum_d;
01165         stree_fun_t *fun;
01166         stree_prop_t *prop;
01167         tdata_object_t *tobject;
01168         tdata_item_t *mtitem;
01169         tdata_tvv_t *tvv;
01170         stree_csi_t *member_csi;
01171 
01172 #ifdef DEBUG_TYPE_TRACE
01173         printf("Type a CSI access operation.\n");
01174 #endif
01175         assert(arg_ti->tic == tic_tobject);
01176         tobject = arg_ti->u.tobject;
01177 
01178         /* Look for a member with the specified name. */
01179         member_sym = symbol_search_csi(stype->program, tobject->csi,
01180             access->member_name);
01181 
01182         if (member_sym == NULL) {
01183                 /* No such member found. */
01184                 cspan_print(access->member_name->cspan);
01185                 printf(" Error: CSI '");
01186                 symbol_print_fqn(csi_to_symbol(tobject->csi));
01187                 printf("' has no member named '%s'.\n",
01188                     strtab_get_str(access->member_name->sid));
01189                 stype_note_error(stype);
01190                 *rtitem = stype_recovery_titem(stype);
01191                 return;
01192         }
01193 
01194 #ifdef DEBUG_RUN_TRACE
01195         printf("Found member '%s'.\n",
01196             strtab_get_str(access->member_name->sid));
01197 #endif
01198         /* Check for accessing non-static member in static context. */
01199         if (tobject->static_ref == sn_static &&
01200             !stree_symbol_is_static(member_sym)) {
01201                 cspan_print(access->member_name->cspan);
01202                 printf(" Error: Accessing non-static member '");
01203                 symbol_print_fqn(member_sym);
01204                 printf("' in static context.\n");
01205                 stype_note_error(stype);
01206                 *rtitem = stype_recovery_titem(stype);
01207                 return;
01208         }
01209 
01210         /* Check for accessing static member in non-static context. */
01211         if (tobject->static_ref != sn_static &&
01212             stree_symbol_is_static(member_sym)) {
01213                 cspan_print(access->member_name->cspan);
01214                 printf(" Error: Accessing static member '");
01215                 symbol_print_fqn(member_sym);
01216                 printf("' in non-static context.\n");
01217                 stype_note_error(stype);
01218                 *rtitem = stype_recovery_titem(stype);
01219                 return;
01220         }
01221 
01222         /* Make compiler happy. */
01223         mtitem = NULL;
01224 
01225         switch (member_sym->sc) {
01226         case sc_csi:
01227                 member_csi = symbol_to_csi(member_sym);
01228                 assert(member_csi != NULL);
01229 
01230                 mtitem = tdata_item_new(tic_tobject);
01231                 tobject = tdata_object_new();
01232                 mtitem->u.tobject = tobject;
01233 
01234                 tobject->static_ref = sn_static;
01235                 tobject->csi = member_csi;
01236                 break;
01237         case sc_ctor:
01238                 /* It is not possible to reference a constructor explicitly. */
01239                 assert(b_false);
01240         case sc_deleg:
01241                 cspan_print(access->member_name->cspan);
01242                 printf(" Error: Accessing object member which is a "
01243                     "delegate.\n");
01244                 stype_note_error(stype);
01245                 *rtitem = stype_recovery_titem(stype);
01246                 return;
01247         case sc_enum:
01248                 enum_d = symbol_to_enum(member_sym);
01249                 assert(enum_d != NULL);
01250                 /* Type enum if it has not been typed yet. */
01251                 stype_enum(stype, enum_d);
01252                 mtitem = enum_d->titem;
01253                 break;
01254         case sc_fun:
01255                 fun = symbol_to_fun(member_sym);
01256                 assert(fun != NULL);
01257                 /* Type function header now */
01258                 stype_fun_header(stype, fun);
01259                 mtitem = fun->titem;
01260                 break;
01261         case sc_var:
01262                 var = symbol_to_var(member_sym);
01263                 assert(var != NULL);
01264                 run_texpr(stype->program, member_sym->outer_csi,
01265                     var->type, &mtitem);
01266                 break;
01267         case sc_prop:
01268                 prop = symbol_to_prop(member_sym);
01269                 assert(prop != NULL);
01270                 run_texpr(stype->program, member_sym->outer_csi,
01271                     prop->type, &mtitem);
01272                 break;
01273         }
01274 
01275         /*
01276          * Substitute type arguments in member titem.
01277          *
01278          * Since the CSI can be generic the actual type of the member
01279          * is obtained by substituting our type arguments into the
01280          * (generic) type of the member.
01281          */
01282 
01283         stype_titem_to_tvv(stype, arg_ti, &tvv);
01284         tdata_item_subst(mtitem, tvv, rtitem);
01285 }
01286 
01294 static void stype_access_tarray(stype_t *stype, stree_access_t *access,
01295     tdata_item_t *arg_ti, tdata_item_t **rtitem)
01296 {
01297         (void) stype;
01298         (void) access;
01299         (void) rtitem;
01300 
01301         cspan_print(access->arg->cspan);
01302         printf(" Error: Unimplemented: Accessing array type '");
01303         tdata_item_print(arg_ti);
01304         printf("'.\n");
01305         stype_note_error(stype);
01306         *rtitem = stype_recovery_titem(stype);
01307 }
01308 
01316 static void stype_access_tebase(stype_t *stype, stree_access_t *access,
01317     tdata_item_t *arg_ti, tdata_item_t **rtitem)
01318 {
01319         tdata_ebase_t *tebase;
01320         tdata_enum_t *tenum;
01321         tdata_item_t *mtitem;
01322         stree_embr_t *embr;
01323 
01324 #ifdef DEBUG_TYPE_TRACE
01325         printf("Type an ebase access operation.\n");
01326 #endif
01327         assert(arg_ti->tic == tic_tebase);
01328         tebase = arg_ti->u.tebase;
01329 
01330         /* Look for a member with the specified name. */
01331         embr = stree_enum_find_mbr(tebase->enum_d, access->member_name);
01332 
01333         if (embr == NULL) {
01334                 /* No such member found. */
01335                 cspan_print(access->member_name->cspan);
01336                 printf(" Error: Enum type '");
01337                 symbol_print_fqn(enum_to_symbol(tebase->enum_d));
01338                 printf("' has no member named '%s'.\n",
01339                     strtab_get_str(access->member_name->sid));
01340                 stype_note_error(stype);
01341                 *rtitem = stype_recovery_titem(stype);
01342                 return;
01343         }
01344 
01345 #ifdef DEBUG_RUN_TRACE
01346         printf("Found member '%s'.\n",
01347             strtab_get_str(access->member_name->sid));
01348 #endif
01349 
01350         mtitem = tdata_item_new(tic_tenum);
01351         tenum = tdata_enum_new();
01352         mtitem->u.tenum = tenum;
01353         tenum->enum_d = tebase->enum_d;
01354 
01355         *rtitem = mtitem;
01356 }
01357 
01358 
01365 static void stype_call(stype_t *stype, stree_call_t *call,
01366     tdata_item_t **rtitem)
01367 {
01368         tdata_item_t *fun_ti;
01369         tdata_fun_sig_t *tsig;
01370 
01371 #ifdef DEBUG_TYPE_TRACE
01372         cspan_print(call->expr->cspan);
01373         printf(" Evaluate type of call operation.\n");
01374 #endif
01375         /* Type the function */
01376         stype_expr(stype, call->fun);
01377 
01378         /* Check type item class */
01379         fun_ti = call->fun->titem;
01380         switch (fun_ti->tic) {
01381         case tic_tdeleg:
01382                 tsig = stype_deleg_get_sig(stype, fun_ti->u.tdeleg);
01383                 assert(tsig != NULL);
01384                 break;
01385         case tic_tfun:
01386                 tsig = fun_ti->u.tfun->tsig;
01387                 break;
01388         case tic_ignore:
01389                 *rtitem = stype_recovery_titem(stype);
01390                 return;
01391         default:
01392                 cspan_print(call->fun->cspan);
01393                 printf(" Error: Calling something which is not a function ");
01394                 printf("(found '");
01395                 tdata_item_print(fun_ti);
01396                 printf("').\n");
01397                 stype_note_error(stype);
01398                 *rtitem = stype_recovery_titem(stype);
01399                 return;
01400         }
01401 
01402         /* Type call arguments. */
01403         stype_call_args(stype, call->expr->cspan, &tsig->arg_ti, tsig->varg_ti,
01404             &call->args);
01405 
01406         if (tsig->rtype != NULL) {
01407                 /* XXX Might be better to clone here. */
01408                 *rtitem = tsig->rtype;
01409         } else {
01410                 *rtitem = NULL;
01411         }
01412 }
01413 
01423 static void stype_call_args(stype_t *stype, cspan_t *cspan, list_t *farg_tis,
01424     tdata_item_t *fvarg_ti, list_t *args)
01425 {
01426         list_node_t *fargt_n;
01427         tdata_item_t *farg_ti;
01428         tdata_item_t *varg_ti;
01429 
01430         list_node_t *arg_n;
01431         stree_expr_t *arg;
01432         stree_expr_t *carg;
01433 
01434         /* Type and check regular arguments. */
01435         fargt_n = list_first(farg_tis);
01436         arg_n = list_first(args);
01437 
01438         while (fargt_n != NULL && arg_n != NULL) {
01439                 farg_ti = list_node_data(fargt_n, tdata_item_t *);
01440                 arg = list_node_data(arg_n, stree_expr_t *);
01441                 stype_expr(stype, arg);
01442 
01443                 /* XXX Because of overloaded bultin WriteLine */
01444                 if (farg_ti == NULL) {
01445                         /* Skip the check */
01446                         fargt_n = list_next(farg_tis, fargt_n);
01447                         arg_n = list_next(args, arg_n);
01448                         continue;
01449                 }
01450 
01451                 /* Convert expression to type of formal argument. */
01452                 carg = stype_convert(stype, arg, farg_ti);
01453 
01454                 /* Patch code with augmented expression. */
01455                 list_node_setdata(arg_n, carg);
01456 
01457                 fargt_n = list_next(farg_tis, fargt_n);
01458                 arg_n = list_next(args, arg_n);
01459         }
01460 
01461         /* Type and check variadic arguments. */
01462         if (fvarg_ti != NULL) {
01463                 /* Obtain type of packed argument. */
01464                 farg_ti = fvarg_ti;
01465 
01466                 /* Get array element type */
01467                 assert(farg_ti->tic == tic_tarray);
01468                 varg_ti = farg_ti->u.tarray->base_ti;
01469 
01470                 while (arg_n != NULL) {
01471                         arg = list_node_data(arg_n, stree_expr_t *);
01472                         stype_expr(stype, arg);
01473 
01474                         /* Convert expression to type of formal argument. */
01475                         carg = stype_convert(stype, arg, varg_ti);
01476 
01477                         /* Patch code with augmented expression. */
01478                         list_node_setdata(arg_n, carg);
01479 
01480                         arg_n = list_next(args, arg_n);
01481                 }
01482         }
01483 
01484         if (fargt_n != NULL) {
01485                 cspan_print(cspan);
01486                 printf(" Error: Too few arguments.\n");
01487                 stype_note_error(stype);
01488         }
01489 
01490         if (arg_n != NULL) {
01491                 cspan_print(cspan);
01492                 printf(" Error: Too many arguments.\n");
01493                 stype_note_error(stype);
01494         }
01495 }
01496 
01503 static void stype_index(stype_t *stype, stree_index_t *index,
01504     tdata_item_t **rtitem)
01505 {
01506         tdata_item_t *base_ti;
01507         list_node_t *arg_n;
01508         stree_expr_t *arg;
01509 
01510 #ifdef DEBUG_TYPE_TRACE
01511         cspan_print(index->expr->cspan);
01512         printf(" Evaluate type of index operation.\n");
01513 #endif
01514         stype_expr(stype, index->base);
01515         base_ti = index->base->titem;
01516 
01517         /* Type the arguments (indices). */
01518         arg_n = list_first(&index->args);
01519         while (arg_n != NULL) {
01520                 arg = list_node_data(arg_n, stree_expr_t *);
01521                 stype_expr(stype, arg);
01522 
01523                 arg_n = list_next(&index->args, arg_n);
01524         }
01525 
01526         switch (base_ti->tic) {
01527         case tic_tprimitive:
01528                 stype_index_tprimitive(stype, index, base_ti, rtitem);
01529                 break;
01530         case tic_tobject:
01531                 stype_index_tobject(stype, index, base_ti, rtitem);
01532                 break;
01533         case tic_tarray:
01534                 stype_index_tarray(stype, index, base_ti, rtitem);
01535                 break;
01536         case tic_tdeleg:
01537                 cspan_print(index->base->cspan);
01538                 printf(" Error: Indexing a delegate.\n");
01539                 stype_note_error(stype);
01540                 *rtitem = stype_recovery_titem(stype);
01541                 break;
01542         case tic_tebase:
01543                 cspan_print(index->base->cspan);
01544                 printf(" Error: Indexing an enum declaration.\n");
01545                 stype_note_error(stype);
01546                 *rtitem = stype_recovery_titem(stype);
01547                 break;
01548         case tic_tenum:
01549                 cspan_print(index->base->cspan);
01550                 printf(" Error: Indexing an enum value.\n");
01551                 stype_note_error(stype);
01552                 *rtitem = stype_recovery_titem(stype);
01553                 break;
01554         case tic_tfun:
01555                 cspan_print(index->base->cspan);
01556                 printf(" Error: Indexing a function.\n");
01557                 stype_note_error(stype);
01558                 *rtitem = stype_recovery_titem(stype);
01559                 break;
01560         case tic_tvref:
01561                 /* Cannot allow this without some constraint. */
01562                 cspan_print(index->base->cspan);
01563                 printf(" Error: Indexing generic data.\n");
01564                 *rtitem = stype_recovery_titem(stype);
01565                 break;
01566         case tic_ignore:
01567                 *rtitem = stype_recovery_titem(stype);
01568                 break;
01569         }
01570 }
01571 
01579 static void stype_index_tprimitive(stype_t *stype, stree_index_t *index,
01580     tdata_item_t *base_ti, tdata_item_t **rtitem)
01581 {
01582         tdata_primitive_t *tprimitive;
01583         tdata_item_t *titem;
01584 
01585         (void) stype;
01586         (void) index;
01587 
01588         assert(base_ti->tic == tic_tprimitive);
01589         tprimitive = base_ti->u.tprimitive;
01590 
01591         if (tprimitive->tpc == tpc_string) {
01592                 titem = tdata_item_new(tic_tprimitive);
01593                 titem->u.tprimitive = tdata_primitive_new(tpc_char);
01594                 *rtitem = titem;
01595                 return;
01596         }
01597 
01598         cspan_print(index->base->cspan);
01599         printf(" Error: Indexing primitive type '");
01600         tdata_item_print(base_ti);
01601         printf("'.\n");
01602         stype_note_error(stype);
01603         *rtitem = stype_recovery_titem(stype);
01604 }
01605 
01613 static void stype_index_tobject(stype_t *stype, stree_index_t *index,
01614     tdata_item_t *base_ti, tdata_item_t **rtitem)
01615 {
01616         tdata_object_t *tobject;
01617         stree_symbol_t *idx_sym;
01618         stree_prop_t *idx;
01619         stree_ident_t *idx_ident;
01620         tdata_item_t *mtitem;
01621         tdata_tvv_t *tvv;
01622 
01623         (void) index;
01624 
01625 #ifdef DEBUG_TYPE_TRACE
01626         cspan_print(index->expr->cspan);
01627         printf(" Indexing object type '");
01628         tdata_item_print(base_ti);
01629         printf("'.\n");
01630 #endif
01631 
01632         assert(base_ti->tic == tic_tobject);
01633         tobject = base_ti->u.tobject;
01634 
01635         /* Find indexer symbol. */
01636         idx_ident = stree_ident_new();
01637         idx_ident->sid = strtab_get_sid(INDEXER_IDENT);
01638         idx_sym = symbol_search_csi(stype->program, tobject->csi, idx_ident);
01639 
01640         if (idx_sym == NULL) {
01641                 cspan_print(index->base->cspan);
01642                 printf(" Error: Indexing object of type '");
01643                 tdata_item_print(base_ti);
01644                 printf("' which does not have an indexer.\n");
01645                 stype_note_error(stype);
01646                 *rtitem = stype_recovery_titem(stype);
01647                 return;
01648         }
01649 
01650         idx = symbol_to_prop(idx_sym);
01651         assert(idx != NULL);
01652 
01653         /* XXX Memoize to avoid recomputing every time. */
01654         run_texpr(stype->program, idx_sym->outer_csi, idx->type, &mtitem);
01655 
01656         /*
01657          * Substitute type arguments in member titem.
01658          *
01659          * Since the CSI can be generic the actual type of the member
01660          * is obtained by substituting our type arguments into the
01661          * (generic) type of the member.
01662          */
01663 
01664         stype_titem_to_tvv(stype, base_ti, &tvv);
01665         tdata_item_subst(mtitem, tvv, rtitem);
01666 }
01667 
01675 static void stype_index_tarray(stype_t *stype, stree_index_t *index,
01676     tdata_item_t *base_ti, tdata_item_t **rtitem)
01677 {
01678         list_node_t *arg_n;
01679         stree_expr_t *arg;
01680         int arg_count;
01681 
01682         (void) stype;
01683         assert(base_ti->tic == tic_tarray);
01684 
01685         /*
01686          * Check that type of all indices is @c int and that the number of
01687          * indices matches array rank.
01688          */
01689         arg_count = 0;
01690         arg_n = list_first(&index->args);
01691         while (arg_n != NULL) {
01692                 ++arg_count;
01693 
01694                 arg = list_node_data(arg_n, stree_expr_t *);
01695                 if (arg->titem->tic != tic_tprimitive ||
01696                     arg->titem->u.tprimitive->tpc != tpc_int) {
01697 
01698                         cspan_print(arg->cspan);
01699                         printf(" Error: Array index is not an integer.\n");
01700                         stype_note_error(stype);
01701                 }
01702 
01703                 arg_n = list_next(&index->args, arg_n);
01704         }
01705 
01706         if (arg_count != base_ti->u.tarray->rank) {
01707                 cspan_print(index->expr->cspan);
01708                 printf(" Error: Using %d indices with array of rank %d.\n",
01709                     arg_count, base_ti->u.tarray->rank);
01710                 stype_note_error(stype);
01711         }
01712 
01713         *rtitem = base_ti->u.tarray->base_ti;
01714 }
01715 
01722 static void stype_assign(stype_t *stype, stree_assign_t *assign,
01723     tdata_item_t **rtitem)
01724 {
01725         stree_expr_t *csrc;
01726 
01727 #ifdef DEBUG_TYPE_TRACE
01728         cspan_print(assign->expr->cspan);
01729         printf(" Evaluate type of assignment.\n");
01730 #endif
01731         stype_expr(stype, assign->dest);
01732         stype_expr(stype, assign->src);
01733 
01734         csrc = stype_convert(stype, assign->src, assign->dest->titem);
01735 
01736         /* Patch code with the augmented expression. */
01737         assign->src = csrc;
01738         *rtitem = NULL;
01739 }
01740 
01747 static void stype_as(stype_t *stype, stree_as_t *as_op, tdata_item_t **rtitem)
01748 {
01749         tdata_item_t *titem;
01750         tdata_item_t *pred_ti;
01751 
01752 #ifdef DEBUG_TYPE_TRACE
01753         cspan_print(as_op->expr->cspan);
01754         printf(" Evaluate type of @c as conversion.\n");
01755 #endif
01756         stype_expr(stype, as_op->arg);
01757         run_texpr(stype->program, stype->current_csi, as_op->dtype, &titem);
01758 
01759         pred_ti = stype_tobject_find_pred(stype, titem, as_op->arg->titem);
01760         if (pred_ti == NULL) {
01761                 /* No CSI match. */
01762                 stype_convert_failure(stype, convc_as, as_op->arg, titem);
01763                 *rtitem = titem;
01764                 return;
01765         }
01766 
01767         /*
01768          * Verify that type arguments match with those specified for
01769          * conversion destination.
01770          */
01771         if (stype_targs_check_equal(stype, pred_ti, as_op->arg->titem)
01772             != EOK) {
01773                 stype_convert_failure(stype, convc_as, as_op->arg, titem);
01774                 *rtitem = titem;
01775                 return;
01776         }
01777 
01778         *rtitem = titem;
01779 }
01780 
01790 static void stype_box(stype_t *stype, stree_box_t *box, tdata_item_t **rtitem)
01791 {
01792         tdata_item_t *ptitem, *btitem;
01793         tdata_object_t *tobject;
01794         stree_symbol_t *csi_sym;
01795         builtin_t *bi;
01796 
01797 #ifdef DEBUG_TYPE_TRACE
01798         cspan_print(box->expr->cspan);
01799         printf(" Evaluate type of boxing operation.\n");
01800 #endif
01801         bi = stype->program->builtin;
01802 
01803         stype_expr(stype, box->arg);
01804         ptitem = box->arg->titem;
01805 
01806         /* Make compiler happy. */
01807         csi_sym = NULL;
01808 
01809         assert(ptitem->tic == tic_tprimitive);
01810         switch (ptitem->u.tprimitive->tpc) {
01811         case tpc_bool: csi_sym = bi->boxed_bool; break;
01812         case tpc_char: csi_sym = bi->boxed_char; break;
01813         case tpc_int: csi_sym = bi->boxed_int; break;
01814         case tpc_nil: assert(b_false);
01815         case tpc_string: csi_sym = bi->boxed_string; break;
01816         case tpc_resource: assert(b_false);
01817         }
01818 
01819         btitem = tdata_item_new(tic_tobject);
01820         tobject = tdata_object_new();
01821 
01822         btitem->u.tobject = tobject;
01823         tobject->static_ref = sn_nonstatic;
01824         tobject->csi = symbol_to_csi(csi_sym);
01825         assert(tobject->csi != NULL);
01826         list_init(&tobject->targs);
01827 
01828         *rtitem = btitem;
01829 }

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