"Fossies" - the Fresh Open Source Software Archive

Member "asymptote-2.61/exp.cc" (18 Nov 2019, 33877 Bytes) of package /linux/misc/asymptote-2.61.src.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "exp.cc" see the Fossies "Dox" file reference documentation.

    1 /*****
    2  * exp.cc
    3  * andy hammerlindl 2002/8/19
    4  *
    5  * represents the abstract syntax tree for the expressions in the
    6  * language.  this is translated into virtual machine code using trans()
    7  * and with the aid of the environment class.
    8  *****/
    9 
   10 #include "exp.h"
   11 #include "errormsg.h"
   12 #include "runtime.h"
   13 #include "runmath.h"
   14 #include "runpicture.h"
   15 #include "runarray.h"
   16 #include "runpair.h"
   17 #include "runtriple.h"
   18 #include "runpath.h"
   19 #include "coenv.h"
   20 #include "application.h"
   21 #include "dec.h"
   22 #include "stm.h"
   23 #include "inst.h"
   24 #include "opsymbols.h"
   25 #include "process.h"
   26 
   27 //void runCode(absyntax::block *code);
   28   
   29 namespace absyntax {
   30 
   31 using namespace types;
   32 using namespace trans;
   33 using vm::inst;
   34 using mem::vector;
   35 
   36 
   37 #if 0
   38 void exp::prettyprint(ostream &out, Int indent)
   39 {
   40   prettyname(out, "exp",indent);
   41 }
   42 #endif
   43 
   44 void exp::transAsType(coenv &e, types::ty *target) {
   45   trans(e);
   46 //  types::ty *t=trans(e);
   47 //  assert(t->kind==ty_error || equivalent(t,target));
   48 }
   49 
   50 void exp::transToType(coenv &e, types::ty *target)
   51 {
   52   types::ty *ct=cgetType(e);
   53 
   54   if (equivalent(target, ct)) {
   55     transAsType(e, target);
   56     return;
   57   }
   58 
   59   // See if the cast can be handled by the fastLookupCast method, which does
   60   // less memory allocation.
   61   if (ct->kind != ty_overloaded &&
   62       ct->kind != ty_error &&
   63       target->kind != ty_error) {
   64     access *a = e.e.fastLookupCast(target, ct);
   65     if (a) {
   66       transAsType(e, ct);
   67       a->encode(trans::CALL, getPos(), e.c);
   68       return;
   69     }
   70   }
   71 
   72   types::ty *source = e.e.castSource(target, ct, symbol::castsym);
   73   if (source==0) {
   74     if (target->kind != ty_error) {
   75       types::ty *sources=cgetType(e);
   76       em.error(getPos());
   77 
   78       em << "cannot cast ";
   79       if (sources->kind==ty_overloaded)
   80         em << "expression";
   81       else
   82         em << "'" << *sources << "'";
   83       em << " to '" << *target << "'";
   84     }
   85   }
   86   else if (source->kind==ty_overloaded) {
   87     if (target->kind != ty_error) {
   88       em.error(getPos());
   89       em << "expression is ambiguous in cast to '" << *target << "'";
   90     }
   91   }
   92   else {
   93     transAsType(e, source);
   94     e.implicitCast(getPos(), target, source);
   95   }
   96 }
   97 
   98 void exp::testCachedType(coenv &e) {
   99   if (ct != 0) {
  100     types::ty *t = getType(e);
  101     if (!equivalent(t, ct)) {
  102       em.compiler(getPos());
  103       em << "cached type '" << *ct 
  104          << "' doesn't match actual type '" << *t << "'";
  105       em.sync();
  106     }
  107   }
  108 }
  109 
  110 void exp::transCall(coenv &e, types::ty *target)
  111 {
  112   transAsType(e, target);
  113   e.c.encode(inst::popcall);
  114 }
  115 
  116 void exp::transConditionalJump(coenv &e, bool cond, label dest) {
  117   transToType(e, primBoolean());
  118   e.c.useLabel(cond ? inst::cjmp : inst::njmp, dest);
  119 }
  120 
  121 exp *exp::evaluate(coenv &e, types::ty *target) {
  122   return new tempExp(e, this, target);
  123 }
  124 
  125 
  126 tempExp::tempExp(coenv &e, varinit *v, types::ty *t)
  127   : exp(v->getPos()), a(e.c.allocLocal()), t(t)
  128 {
  129   v->transToType(e, t);
  130   a->encode(WRITE, getPos(), e.c);
  131   e.c.encodePop();
  132 }
  133 
  134 void tempExp::prettyprint(ostream &out, Int indent) {
  135   prettyname(out, "tempExp", indent);
  136 }
  137 
  138 types::ty *tempExp::trans(coenv &e) {
  139   a->encode(READ, getPos(), e.c);
  140   return t;
  141 }
  142 
  143 
  144 varEntryExp::varEntryExp(position pos, types::ty *t, access *a)
  145   : exp(pos), v(new trans::varEntry(t, a, 0, position())) {}
  146 varEntryExp::varEntryExp(position pos, types::ty *t, vm::bltin f)
  147   : exp(pos), v(new trans::varEntry(t, new bltinAccess(f), 0, position())) {}
  148 
  149 void varEntryExp::prettyprint(ostream &out, Int indent) {
  150   prettyname(out, "varEntryExp", indent);
  151 }
  152 
  153 types::ty *varEntryExp::getType(coenv &) {
  154   return v->getType();
  155 }
  156 
  157 types::ty *varEntryExp::trans(coenv &e) {
  158   v->encode(READ, getPos(), e.c);
  159   return getType(e);
  160 }
  161 
  162 trans::varEntry *varEntryExp::getCallee(coenv &e, types::signature *sig) {
  163   return equivalent(sig, v->getType()->getSignature()) ? v : 0;
  164 }
  165 
  166 void varEntryExp::transAct(action act, coenv &e, types::ty *target) {
  167   assert(equivalent(getType(e),target));
  168   v->encode(act, getPos(), e.c);
  169 }
  170 void varEntryExp::transAsType(coenv &e, types::ty *target) {
  171   transAct(READ, e, target);
  172 }
  173 void varEntryExp::transWrite(coenv &e, types::ty *target, exp *value) {
  174   value->transToType(e, target);
  175   transAct(WRITE, e, target);
  176 }
  177 void varEntryExp::transCall(coenv &e, types::ty *target) {
  178   transAct(trans::CALL, e, target);
  179 }
  180 
  181 
  182 void nameExp::prettyprint(ostream &out, Int indent)
  183 {
  184   prettyname(out, "nameExp",indent);
  185 
  186   value->prettyprint(out, indent+1);
  187 }
  188 
  189 
  190 void fieldExp::pseudoName::prettyprint(ostream &out, Int indent)
  191 {
  192   // This should never be called.
  193   prettyindent(out, indent);
  194   out << "pseudoName" << "\n";
  195 
  196   object->prettyprint(out, indent+1);
  197 }
  198 
  199 void fieldExp::prettyprint(ostream &out, Int indent)
  200 {
  201   prettyindent(out, indent);
  202   out << "fieldExp '" << field << "'\n";
  203 
  204   object->prettyprint(out, indent+1);
  205 }
  206 
  207 types::ty *fieldExp::getObject(coenv& e)
  208 {
  209   types::ty *t = object->cgetType(e);
  210   if (t->kind == ty_overloaded) {
  211     t=((overloaded *)t)->signatureless();
  212     if(!t) return primError();
  213   }
  214   return t;
  215 }
  216 
  217 
  218 array *arrayExp::getArrayType(coenv &e)
  219 {
  220   types::ty *a = set->cgetType(e);
  221   if (a->kind == ty_overloaded) {
  222     a = ((overloaded *)a)->signatureless();
  223     if (!a)
  224       return 0;
  225   }
  226 
  227   switch (a->kind) {
  228     case ty_array:
  229       return (array *)a;
  230     case ty_error:
  231       return 0;
  232     default:
  233       return 0;
  234   }
  235 }
  236 
  237 array *arrayExp::transArray(coenv &e)
  238 {
  239   types::ty *a = set->cgetType(e);
  240   if (a->kind == ty_overloaded) {
  241     a = ((overloaded *)a)->signatureless();
  242     if (!a) {
  243       em.error(set->getPos());
  244       em << "expression is not an array";
  245       return 0;
  246     }
  247   }
  248 
  249   set->transAsType(e, a);
  250 
  251   switch (a->kind) {
  252     case ty_array:
  253       return (array *)a;
  254     case ty_error:
  255       return 0;
  256     default:
  257       em.error(set->getPos());
  258       em << "expression is not an array";
  259       return 0;
  260   }
  261 }
  262 
  263 // Checks if the expression can be translated as an array.
  264 bool isAnArray(coenv &e, exp *x)
  265 {
  266   types::ty *t=x->cgetType(e);
  267   if (t->kind == ty_overloaded)
  268     t=dynamic_cast<overloaded *>(t)->signatureless();
  269   return t && t->kind==ty_array;
  270 }
  271 
  272 
  273 void subscriptExp::prettyprint(ostream &out, Int indent)
  274 {
  275   prettyindent(out, indent);
  276   out << "subscriptExp\n";
  277 
  278   set->prettyprint(out, indent+1);
  279   index->prettyprint(out, indent+1);
  280 }
  281 
  282 types::ty *subscriptExp::trans(coenv &e)
  283 {
  284   array *a = transArray(e);
  285   if (!a)
  286     return primError();
  287 
  288   if (isAnArray(e, index)) {
  289     index->transToType(e, types::IntArray());
  290     e.c.encode(inst::builtin, run::arrayIntArray);
  291     return getArrayType(e);
  292   }
  293   else {
  294     index->transToType(e, types::primInt());
  295     e.c.encode(inst::builtin,
  296                a->celltype->kind==ty_array ? run::arrayArrayRead :
  297                run::arrayRead);
  298     return a->celltype;
  299   }
  300 }
  301 
  302 types::ty *subscriptExp::getType(coenv &e)
  303 {
  304   array *a = getArrayType(e);
  305   return a ? (isAnArray(e, index) ? a : a->celltype) :
  306     primError();
  307 }
  308      
  309 void subscriptExp::transWrite(coenv &e, types::ty *t, exp *value)
  310 {
  311   // Put array, index, and value on the stack in that order, then call
  312   // arrayWrite.
  313   array *a = transArray(e);
  314   if (!a)
  315     return;
  316 
  317   if (!equivalent(a->celltype, t))
  318   {
  319     em.error(getPos());
  320     em << "array expression cannot be used as an address";
  321 
  322     // Translate the value for errors.
  323     value->transToType(e, t);
  324     return;
  325   }
  326 
  327   index->transToType(e, types::primInt());
  328 
  329   value->transToType(e, t);
  330 
  331   e.c.encode(inst::builtin, run::arrayWrite);
  332 }
  333 
  334 
  335 void slice::prettyprint(ostream &out, Int indent)
  336 {
  337   prettyname(out, "slice", indent);
  338   if (left)
  339     left->prettyprint(out, indent+1);
  340   else
  341     prettyname(out, "left omitted", indent+1);
  342   if (right)
  343     right->prettyprint(out, indent+1);
  344   else
  345     prettyname(out, "right omitted", indent+1);
  346 }
  347 
  348 void slice::trans(coenv &e)
  349 {
  350   if (left)
  351     left->transToType(e, types::primInt());
  352   else
  353     // If the left index is omitted it can be assumed to be zero.
  354     e.c.encode(inst::intpush, (Int)0);
  355 
  356   if (right)
  357     right->transToType(e, types::primInt());
  358 }
  359 
  360 
  361 void sliceExp::prettyprint(ostream &out, Int indent)
  362 {
  363   prettyname(out, "sliceExp", indent);
  364   set->prettyprint(out, indent+1);
  365   index->prettyprint(out, indent+1);
  366 }
  367 
  368 types::ty *sliceExp::trans(coenv &e)
  369 {
  370   array *a = transArray(e);
  371   if (!a)
  372     return primError();
  373 
  374   index->trans(e);
  375 
  376   e.c.encode(inst::builtin, index->getRight() ? run::arraySliceRead :
  377              run::arraySliceReadToEnd);
  378 
  379   return a;
  380 }
  381 
  382 types::ty *sliceExp::getType(coenv &e)
  383 {
  384   array *a = getArrayType(e);
  385   return a ? a : primError();
  386 }
  387 
  388 void sliceExp::transWrite(coenv &e, types::ty *t, exp *value)
  389 {
  390   array *a = transArray(e);
  391   if (!a)
  392     return;
  393   assert(equivalent(a, t));
  394 
  395   index->trans(e);
  396 
  397   value->transToType(e, t);
  398 
  399   e.c.encode(inst::builtin, index->getRight() ? run::arraySliceWrite :
  400              run::arraySliceWriteToEnd);
  401 }
  402 
  403 void thisExp::prettyprint(ostream &out, Int indent)
  404 {
  405   prettyname(out, "thisExp", indent);
  406 }
  407 
  408 types::ty *thisExp::trans(coenv &e)
  409 {
  410   if (!e.c.encodeThis()) {
  411     em.error(getPos());
  412     em << "static use of 'this' expression";
  413   }
  414   return cgetType(e);
  415 }
  416 
  417 types::ty *thisExp::getType(coenv &e)
  418 {
  419   return e.c.thisType();
  420 }
  421 
  422 void equalityExp::prettyprint(ostream &out, Int indent)
  423 {
  424   prettyname(out, "equalityExp", indent);
  425   callExp::prettyprint(out, indent+1);
  426 }
  427 
  428 types::ty *equalityExp::getType(coenv &e) {
  429   // Try to the resolve the expression as a function call first.
  430   types::ty *t = callExp::getType(e);
  431   assert(t);
  432   if (t->kind != ty_error)
  433     return t;
  434   else
  435     // Either an error or handled by the function equality methods.  In the
  436     // first case, we may return whatever we like, and the second case always
  437     // returns bool.  In either case, it is safe to return bool.
  438     return primBoolean();
  439 }
  440 
  441 // From a possibly overloaded type, if there is a unique function type, return
  442 // it, otherwise 0.
  443 types::ty *uniqueFunction(types::ty *t) {
  444   if (t->kind == types::ty_function)
  445     return t;
  446 
  447   if (t->isOverloaded()) {
  448     types::ty *ft = 0;
  449     for (ty_iterator i = t->begin(); i != t->end(); ++i)
  450     {
  451       if ((*i)->kind != types::ty_function) 
  452         continue;
  453 
  454       if (ft) {
  455         // Multiple function types.
  456         return 0;
  457       }
  458 
  459       ft = *i;
  460     }
  461 
  462     return ft;
  463   }
  464 
  465   // Not a function.
  466   return 0;
  467 }
  468 
  469 // From two possibly overloaded types, if there is a unique function type
  470 // common to both, return it, otherwise 0.
  471 types::ty *uniqueFunction(types::ty *t1, types::ty *t2) {
  472   if (t1->kind == types::ty_function)
  473     return equivalent(t1, t2) ? t1 : 0;
  474 
  475   if (t1->isOverloaded()) {
  476     types::ty *ft = 0;
  477     for (ty_iterator i = t1->begin(); i != t1->end(); ++i)
  478     {
  479       if ((*i)->kind != types::ty_function) 
  480         continue;
  481 
  482       if (!equivalent(*i, t2))
  483         continue;
  484 
  485       if (ft) {
  486         // Multiple function types.
  487         return 0;
  488       }
  489 
  490       ft = *i;
  491     }
  492 
  493     return ft;
  494   }
  495 
  496   // Not a function.
  497   return 0;
  498 }
  499 
  500 bltin bltinFromName(symbol name) {
  501   if (name == SYM_EQ)
  502     return run::boolFuncEq;
  503   assert(name == SYM_NEQ);
  504   return run::boolFuncNeq;
  505 }
  506 
  507 types::ty *equalityExp::trans(coenv &e) {
  508   // First, try to handle by normal function resolution.
  509   types::ty *t = callExp::getType(e);
  510   assert(t);
  511   if (t->kind != ty_error)
  512     return callExp::trans(e);
  513 
  514   // Then, check for the function equality case.
  515   exp *left = (*this->args)[0].val;
  516   exp *right = (*this->args)[1].val;
  517 
  518   types::ty *lt = left->getType(e);
  519   types::ty *rt = right->getType(e);
  520 
  521   // TODO: decide what null == null should do.
  522 
  523   // Check for function == null and null == function
  524   types::ty *ft = 0;
  525   if (rt->kind == types::ty_null)
  526     ft = uniqueFunction(lt);
  527   else if (lt->kind == types::ty_null)
  528     ft = uniqueFunction(rt);
  529   else
  530     ft = uniqueFunction(lt, rt);
  531 
  532 
  533   if (ft) {
  534     assert(ft->kind == ty_function);
  535 
  536     left->transToType(e, ft);
  537     right->transToType(e, ft);
  538     e.c.encode(inst::builtin, bltinFromName(callee->getName()));
  539 
  540     return primBoolean();
  541   } else {
  542     // Let callExp report a "no such function" error.
  543     types::ty *t = callExp::trans(e);
  544     assert(t->kind == ty_error);
  545     return t;
  546   }
  547 }
  548 
  549 void scaleExp::prettyprint(ostream &out, Int indent)
  550 {
  551   exp *left=getLeft(); exp *right=getRight();
  552 
  553   prettyname(out, "scaleExp",indent);
  554   left->prettyprint(out, indent+1);
  555   right->prettyprint(out, indent+1);
  556 }
  557 
  558 types::ty *scaleExp::trans(coenv &e)
  559 {
  560   exp *left=getLeft(); exp *right=getRight();
  561 
  562   types::ty *lt = left->cgetType(e);
  563   if (lt->kind != types::ty_Int && lt->kind != types::ty_real) {
  564     if (lt->kind != types::ty_error) {
  565       em.error(left->getPos());
  566       em << "only numeric constants can do implicit scaling";
  567     }
  568     right->trans(e);
  569     return types::primError();
  570   }
  571 
  572   if (!right->scalable()) {
  573     em.warning(right->getPos());
  574     em << "implicit scaling may be unintentional";
  575   }
  576 
  577   // Defer to the binaryExp for multiplication.
  578   return binaryExp::trans(e);
  579 }
  580 
  581 
  582 void intExp::prettyprint(ostream &out, Int indent)
  583 {
  584   prettyindent(out,indent);
  585   out << "intExp: " << value << "\n";
  586 }
  587 
  588 types::ty *intExp::trans(coenv &e)
  589 {
  590   e.c.encode(inst::intpush,value);
  591   
  592   return types::primInt();  
  593 }
  594 
  595 
  596 void realExp::prettyprint(ostream &out, Int indent)
  597 {
  598   prettyindent(out, indent);
  599   out << "realExp: " << value << "\n";
  600 }
  601 
  602 types::ty *realExp::trans(coenv &e)
  603 {
  604   e.c.encode(inst::constpush,(item)value);
  605   
  606   return types::primReal();  
  607 }
  608 
  609 void stringExp::prettyprint(ostream &out, Int indent)
  610 {
  611   prettyindent(out, indent);
  612   out << "stringExp '" << str << "'\n";
  613 }
  614 
  615 types::ty *stringExp::trans(coenv &e)
  616 {
  617   e.c.encode(inst::constpush,(item) string(str));
  618   
  619   return types::primString();  
  620 }
  621 
  622 
  623 void booleanExp::prettyprint(ostream &out, Int indent)
  624 {
  625   prettyindent(out, indent);
  626   out << "booleanExp: " << value << "\n";
  627 }
  628 
  629 types::ty *booleanExp::trans(coenv &e)
  630 {
  631   e.c.encode(inst::constpush,(item)value);
  632   
  633   return types::primBoolean();  
  634 }
  635 
  636 void newPictureExp::prettyprint(ostream &out, Int indent)
  637 {
  638   prettyname(out, "newPictureExp",indent);
  639 }
  640 
  641 types::ty *newPictureExp::trans(coenv &e)
  642 {
  643   e.c.encode(inst::builtin, run::newPicture);
  644   
  645   return types::primPicture();  
  646 }
  647 
  648 void cycleExp::prettyprint(ostream &out, Int indent)
  649 {
  650   prettyname(out, "cycleExp",indent);
  651 }
  652 
  653 types::ty *cycleExp::trans(coenv &e)
  654 {
  655   e.c.encode(inst::builtin, run::newCycleToken);
  656   
  657   return types::primCycleToken();  
  658 }
  659 
  660 void nullPathExp::prettyprint(ostream &out, Int indent)
  661 {
  662   prettyname(out, "nullPathExp",indent);
  663 }
  664 
  665 types::ty *nullPathExp::trans(coenv &e)
  666 {
  667   e.c.encode(inst::builtin, run::nullPath);
  668   
  669   return types::primPath();  
  670 }
  671 
  672 void nullExp::prettyprint(ostream &out, Int indent)
  673 {
  674   prettyname(out, "nullExp",indent);
  675 }
  676 
  677 types::ty *nullExp::trans(coenv &)
  678 {
  679   // Things get put on the stack when ty_null
  680   // is cast to an appropriate type
  681   return types::primNull();  
  682 }
  683 
  684 
  685 void quoteExp::prettyprint(ostream &out, Int indent)
  686 {
  687   prettyname(out, "quoteExp", indent);
  688   value->prettyprint(out, indent+1);
  689 }
  690 
  691 types::ty *quoteExp::trans(coenv &e)
  692 {
  693   e.c.encode(inst::constpush,(item)value);
  694   
  695   return types::primCode();  
  696 }
  697 
  698 void explist::prettyprint(ostream &out, Int indent)
  699 {
  700   prettyname(out, "explist",indent);
  701   for (expvector::iterator p = exps.begin();
  702        p != exps.end(); ++p)
  703     (*p)->prettyprint(out, indent+1);
  704 }
  705 
  706 
  707 void argument::prettyprint(ostream &out, Int indent)
  708 {
  709   prettyindent(out, indent);
  710   out << "explist";
  711   if (name)
  712     out << " '" << name << "'";
  713   out << '\n';
  714 
  715   val->prettyprint(out, indent+1);
  716 }
  717 
  718 void arglist::prettyprint(ostream &out, Int indent)
  719 {
  720   prettyname(out, "arglist",indent);
  721   for (argvector::iterator p = args.begin();
  722        p != args.end(); ++p)
  723     p->prettyprint(out, indent+1);
  724 }
  725 
  726 void callExp::prettyprint(ostream &out, Int indent)
  727 {
  728   prettyname(out, "callExp",indent);
  729 
  730   callee->prettyprint(out, indent+1);
  731   args->prettyprint(out, indent+1);
  732 }
  733 
  734 signature *callExp::argTypes(coenv &e, bool *searchable)
  735 {
  736   signature *source=new signature;
  737 
  738   // The signature is searchable unless one of the arguments is overloaded or
  739   // named.
  740   *searchable = true;
  741 
  742   size_t n = args->size();
  743   
  744   for (size_t i = 0; i < n; i++) {
  745     if(string(args->args[i].name) == "KEY") {
  746       stringExp *s=dynamic_cast<stringExp*>(args->args[i].val);
  747       if(s) {
  748         if(getPos().filename() == processData().fileName)
  749           processData().xkey[getPos().LineColumn()]=Strdup(s->getString());
  750         args->args.erase(args->args.begin()+i);
  751         --n;
  752         if(i == n) break;
  753       }
  754     }
  755 
  756     argument a=(*args)[i];
  757     types::ty *t = a.val->cgetType(e);
  758     if (t->kind == types::ty_error)
  759       return 0;
  760     if (t->kind == types::ty_overloaded || a.name)
  761       *searchable = false;
  762     source->add(types::formal(t,a.name));
  763   }
  764 
  765   if (args->rest.val) {
  766     argument a=args->rest;
  767     types::ty *t = a.val->cgetType(e);
  768     if (t->kind == types::ty_error)
  769       return 0;
  770     if (t->kind == types::ty_overloaded || a.name)
  771       *searchable = false;
  772     source->addRest(types::formal(t,a.name));
  773   }
  774 
  775   return source;
  776 }
  777 
  778 application *callExp::resolve(coenv &e, overloaded *o, signature *source,
  779                               bool tacit) {
  780   app_list l=multimatch(e.e, o, source, *args);
  781 
  782   if (l.empty()) {
  783     //cerr << "l is empty\n";
  784     if (!tacit) {
  785       em.error(getPos());
  786 
  787       symbol s = callee->getName();
  788       if (s)
  789         em << "no matching function \'" << s;
  790       else
  791         em << "no matching function for signature \'";
  792       em << *source << "\'";
  793     }
  794 
  795     return 0;
  796   }
  797   else if (l.size() > 1) { // This may take O(n) time.
  798     //cerr << "l is full\n";
  799     if (!tacit) {
  800       em.error(getPos());
  801 
  802       symbol s = callee->getName();
  803       if(s)
  804         em << "call of function \'" << s;
  805       else
  806         em << "call with signature \'";
  807       em << *source << "\' is ambiguous";
  808     }
  809 
  810     return 0;
  811   }
  812   else {
  813     //cerr << "l is singleton\n";
  814     return l.front();
  815   }
  816 }
  817 
  818 bool hasNamedParameters(signature *sig) {
  819   for (size_t i=0; i < sig->getNumFormals(); ++i)
  820     if (sig->getFormal(i).name)
  821       return true;
  822   return false;
  823 }
  824 
  825 void callExp::reportMismatch(function *ft, signature *source)
  826 {
  827   symbol s = callee->getName();
  828   const char *separator=ft->getSignature()->getNumFormals() > 1 ? "\n" : " ";
  829 
  830   em.error(getPos());
  831   em << "cannot call" << separator << "'" << *ft->getResult() << " ";
  832   if(s)
  833     em << s;
  834   em << *ft->getSignature() << "'" << separator;
  835 
  836   if (ft->getSignature()->isOpen && hasNamedParameters(source))
  837     em << "with named parameters";
  838   else
  839     switch(source->getNumFormals()) {
  840       case 0:
  841         em << "without parameters";
  842         break;
  843       case 1:
  844         em << "with parameter '" << *source << "'";
  845         break;
  846       default:
  847         em << "with parameters\n'" << *source << "'";
  848     }
  849 }
  850 
  851 void callExp::reportArgErrors(coenv &e)
  852 {
  853   // Cycle through the parameters to report all errors.
  854   // NOTE: This may report inappropriate ambiguity errors. 
  855   for (size_t i = 0; i < args->size(); i++) {
  856     (*args)[i].val->trans(e);
  857   }
  858   if (args->rest.val)
  859     args->rest.val->trans(e);
  860 }
  861 
  862 void callExp::reportNonFunction() {
  863     em.error(getPos());
  864     symbol s = callee->getName();
  865     if (s)
  866       em << "\'" << s << "\' is not a function";
  867     else
  868       em << "called expression is not a function";
  869 }
  870 
  871 types::ty *callExp::cacheAppOrVarEntry(coenv &e, bool tacit)
  872 {
  873   assert(cachedVarEntry == 0 && cachedApp == 0);
  874 
  875   // First figure out the signature of what we want to call.
  876   bool searchable;
  877   signature *source=argTypes(e, &searchable);
  878 
  879 #ifdef DEBUG_GETAPP /* {{{ */
  880   cout << "getApp for ";
  881   if (callee->getName())
  882     cout << *callee->getName();
  883   else 
  884     cout << "unnamed";
  885   cout << " at " << getPos() << endl;
  886   cout << "searchable: " << searchable << endl;
  887 #endif /* }}} */
  888 
  889   if (!source) {
  890     return primError();
  891   }
  892 
  893   // An attempt at speeding up compilation:  See if the source arguments match
  894   // the (possibly overloaded) function exactly.
  895   if (searchable) {
  896     varEntry *ve = callee->getCallee(e, source);
  897 
  898 #ifdef DEBUG_GETAPP
  899     cout << "guessed: " << (ve!=0) << endl;
  900 #endif
  901 
  902     if (ve) {
  903       cachedVarEntry = ve;
  904 #ifndef DEBUG_CACHE
  905       // Normally DEBUG_CACHE is not defined and we return here for efficiency
  906       // reasons.  If DEBUG_CACHE is defined, we instead proceed to resolve
  907       // the function by the normal techniques and make sure we get the same
  908       // result.
  909       return ((function *)ve->getType())->getResult();
  910 #endif
  911     }
  912   }
  913 
  914   // Figure out what function types we can call.
  915   types::ty *ft = callee->cgetType(e);
  916 
  917 #ifdef DEBUG_GETAPP
  918   string name = callee->getName() ? string(*callee->getName()) :
  919                                     string("unnamed");
  920   if (!callee->getName())
  921     cout << getPos() << endl;
  922 #endif
  923 
  924   switch (ft->kind) {
  925     case ty_error:
  926       if (!tacit)
  927         // Report callee errors.
  928         callee->trans(e);
  929       break;
  930 
  931     case ty_function:
  932       //cout << "name " << name << endl;
  933       cachedApp = application::match(e.e, (function *)ft, source, *args);
  934       if (!cachedApp && !tacit)
  935         reportMismatch((function *)ft, source);
  936       break;
  937 
  938     case ty_overloaded: {
  939 #ifdef DEBUG_GETAPP
  940       int size = ((overloaded *)ft)->sub.size();
  941       for (int i = 0; i < size; ++i) cout << "name " << name << endl;
  942 #endif
  943       cachedApp = resolve(e, (overloaded *)ft, source, tacit);
  944       break;
  945     }
  946 
  947     default:
  948       if (!tacit)
  949         reportNonFunction();
  950       break;
  951   }
  952 
  953 #ifdef DEBUG_GETAPP
  954   cout << name << " " << *source << " --> "
  955        << *cachedApp->getType()->getSignature() << endl;
  956 #endif
  957 
  958 #if DEBUG_CACHE
  959   // Make sure cachedVarEntry is giving us the right function.
  960   if (cachedVarEntry)
  961     assert(equivalent(cachedVarEntry->getType(), cachedApp->getType()));
  962 #endif
  963 
  964   // getType relies on this method for the type.
  965   return cachedApp ? cachedApp->getType()->getResult() : primError();
  966 }
  967 
  968 types::ty *callExp::transPerfectMatch(coenv &e) {
  969   // The varEntry of the callee.  (No longer needed after translation.)
  970   varEntry *ve = cachedVarEntry;
  971   cachedVarEntry = 0;
  972   assert(ve);
  973 
  974   // Translate the arguments in turn.
  975   for (size_t i = 0; i < args->size(); ++i)
  976     (*args)[i].val->trans(e);
  977   if (args->rest.val)
  978     args->rest.val->trans(e);
  979 
  980   // Call the function.
  981   ve->encode(trans::CALL, getPos(), e.c);
  982 
  983   // That's it.  Return the return type of the function.
  984   return ct ? ct : dynamic_cast<function *>(ve->getType())->getResult();
  985 }
  986 
  987 types::ty *callExp::trans(coenv &e)
  988 {
  989   if (cachedVarEntry == 0 && cachedApp == 0)
  990     cacheAppOrVarEntry(e, false);
  991 
  992   if (cachedVarEntry)
  993     return transPerfectMatch(e);
  994 
  995   // The cached data is no longer needed after translation, so let it be
  996   // garbage collected.
  997   application *a = cachedApp;
  998   cachedApp=0;
  999 
 1000   if (!a) {
 1001     reportArgErrors(e);
 1002     return primError();
 1003   }
 1004 
 1005   // To simulate left-to-right order of evaluation, produce the
 1006   // side-effects for the callee.
 1007   assert(a);
 1008   function *t=a->getType();
 1009   assert(t);
 1010   exp *temp=callee->evaluate(e, t);
 1011 
 1012   // Let the application handle the argument translation.
 1013   a->transArgs(e);
 1014 
 1015   // Translate the call.
 1016   temp->transCall(e, t);
 1017 
 1018   return t->result;
 1019 }
 1020 
 1021 types::ty *callExp::getType(coenv &e)
 1022 {
 1023   if (cachedApp)
 1024     return cachedApp->getType()->getResult();
 1025   if (cachedVarEntry) {
 1026     function *ft = dynamic_cast<function *>(cachedVarEntry->getType());
 1027     assert(ft);
 1028     return ft->getResult();
 1029   }
 1030   return cacheAppOrVarEntry(e, true);
 1031 }
 1032 
 1033 bool callExp::resolved(coenv &e) {
 1034   if (cachedApp == 0 && cachedVarEntry == 0)
 1035     cacheAppOrVarEntry(e, true);
 1036   return cachedApp || cachedVarEntry;
 1037 }
 1038   
 1039     
 1040 void pairExp::prettyprint(ostream &out, Int indent)
 1041 {
 1042   prettyname(out, "pairExp",indent);
 1043 
 1044   x->prettyprint(out, indent+1);
 1045   y->prettyprint(out, indent+1);
 1046 }
 1047 
 1048 types::ty *pairExp::trans(coenv &e)
 1049 {
 1050   x->transToType(e, types::primReal());
 1051   y->transToType(e, types::primReal());
 1052 
 1053   e.c.encode(inst::builtin, run::realRealToPair);
 1054 
 1055   return types::primPair();
 1056 }
 1057 
 1058 void tripleExp::prettyprint(ostream &out, Int indent)
 1059 {
 1060   prettyname(out, "tripleExp",indent);
 1061 
 1062   x->prettyprint(out, indent+1);
 1063   y->prettyprint(out, indent+1);
 1064   z->prettyprint(out, indent+1);
 1065 }
 1066 
 1067 types::ty *tripleExp::trans(coenv &e)
 1068 {
 1069   x->transToType(e, types::primReal());
 1070   y->transToType(e, types::primReal());
 1071   z->transToType(e, types::primReal());
 1072 
 1073   e.c.encode(inst::builtin, run::realRealRealToTriple);
 1074 
 1075   return types::primTriple();
 1076 }
 1077 
 1078 void transformExp::prettyprint(ostream &out, Int indent)
 1079 {
 1080   prettyname(out, "transformExp",indent);
 1081 
 1082   x->prettyprint(out, indent+1);
 1083   y->prettyprint(out, indent+1);
 1084   xx->prettyprint(out, indent+1);
 1085   xy->prettyprint(out, indent+1);
 1086   yx->prettyprint(out, indent+1);
 1087   yy->prettyprint(out, indent+1);
 1088 }
 1089 
 1090 types::ty *transformExp::trans(coenv &e)
 1091 {
 1092   x->transToType(e, types::primReal());
 1093   y->transToType(e, types::primReal());
 1094   xx->transToType(e, types::primReal());
 1095   xy->transToType(e, types::primReal());
 1096   yx->transToType(e, types::primReal());
 1097   yy->transToType(e, types::primReal());
 1098 
 1099   e.c.encode(inst::builtin, run::real6ToTransform);
 1100 
 1101   return types::primTransform();
 1102 }
 1103 
 1104 void castExp::prettyprint(ostream &out, Int indent)
 1105 {
 1106   prettyname(out, "castExp",indent);
 1107 
 1108   target->prettyprint(out, indent+1);
 1109   castee->prettyprint(out, indent+1);
 1110 }
 1111 
 1112 types::ty *castExp::tryCast(coenv &e, types::ty *t, types::ty *s,
 1113                             symbol csym)
 1114 {
 1115   types::ty *ss=e.e.castSource(t, s, csym);
 1116   if (ss == 0) {
 1117     return 0;
 1118   }
 1119   if (ss->kind == ty_overloaded) {
 1120     em.error(getPos());
 1121     em << "cast is ambiguous";
 1122     return primError();
 1123   }
 1124   else {
 1125     castee->transAsType(e, ss);
 1126 
 1127     access *a=e.e.lookupCast(t, ss, csym);
 1128     assert(a);
 1129     a->encode(trans::CALL, getPos(), e.c);
 1130     return ss;
 1131   }
 1132 }
 1133 
 1134 types::ty *castExp::trans(coenv &e)
 1135 {
 1136   target->addOps(e, (record *)0);
 1137   types::ty *t=target->trans(e);
 1138 
 1139   types::ty *s=castee->cgetType(e);
 1140 
 1141   if (!tryCast(e, t, s, symbol::ecastsym))
 1142     if (!tryCast(e, t, s, symbol::castsym)) {
 1143       em.error(getPos());
 1144       em << "cannot cast '" << *s << "' to '" << *t << "'";
 1145     }
 1146 
 1147   return t;
 1148 }
 1149 
 1150 types::ty *castExp::getType(coenv &e)
 1151 {
 1152   return target->trans(e, true);
 1153 }
 1154 
 1155 
 1156 void conditionalExp::prettyprint(ostream &out, Int indent)
 1157 {
 1158   prettyname(out, "conditionalExp",indent);
 1159 
 1160   test->prettyprint(out, indent+1);
 1161   onTrue->prettyprint(out, indent+1);
 1162   onFalse->prettyprint(out, indent+1);
 1163 }
 1164 
 1165 void conditionalExp::baseTransToType(coenv &e, types::ty *target) {
 1166   test->transToType(e, types::primBoolean());
 1167 
 1168   label tlabel = e.c.fwdLabel();
 1169   e.c.useLabel(inst::cjmp,tlabel);
 1170 
 1171   onFalse->transToType(e, target);
 1172 
 1173   label end = e.c.fwdLabel();
 1174   e.c.useLabel(inst::jmp,end);
 1175 
 1176   e.c.defLabel(tlabel);
 1177   onTrue->transToType(e, target);
 1178 
 1179   e.c.defLabel(end);
 1180 }
 1181 
 1182 void conditionalExp::transToType(coenv &e, types::ty *target)
 1183 {
 1184   if (isAnArray(e, test)) {
 1185     if (target->kind != ty_array) {
 1186       em.error(getPos());
 1187       em << "cannot cast vectorized conditional to '" << *target << "'";
 1188     }
 1189     test->transToType(e, types::booleanArray());
 1190     onTrue->transToType(e, target);
 1191     onFalse->transToType(e, target);
 1192     e.c.encode(inst::builtin, run::arrayConditional);
 1193   }
 1194   else {
 1195     baseTransToType(e, target);
 1196   }
 1197 }
 1198 
 1199 types::ty *promote(coenv &e, types::ty *x, types::ty *y)
 1200 {
 1201   struct promoter : public collector {
 1202     env &e;
 1203 
 1204     promoter(env &e)
 1205       : e(e) {}
 1206 
 1207     types::ty *both (types::ty *x, types::ty *y) {
 1208       overloaded *o=new overloaded;
 1209       o->add(x); o->add(y);
 1210       return o;
 1211     }
 1212 
 1213     types::ty *base (types::ty *x, types::ty *y) {
 1214       if (equivalent(x,y))
 1215         return x;
 1216       else {
 1217         bool castToFirst=e.castable(x, y, symbol::castsym);
 1218         bool castToSecond=e.castable(y, x, symbol::castsym);
 1219 
 1220         return (castToFirst && castToSecond) ? both(x,y) : 
 1221           castToFirst ? x :
 1222           castToSecond ? y :
 1223           0;
 1224       }
 1225     }
 1226   };
 1227 
 1228   promoter p(e.e);
 1229   return p.collect(x,y);
 1230 }
 1231 
 1232 types::ty *conditionalExp::trans(coenv &e)
 1233 {
 1234   types::ty *tt=onTrue->cgetType(e);
 1235   types::ty *ft=onFalse->cgetType(e);
 1236 
 1237   if (tt->kind==ty_error)
 1238     return onTrue->trans(e);
 1239   if (ft->kind==ty_error)
 1240     return onFalse->trans(e);
 1241 
 1242   types::ty *t=promote(e, tt, ft);
 1243   if (!t) {
 1244     em.error(getPos());
 1245     em << "types in conditional expression do not match";
 1246     return primError();
 1247   }
 1248   else if (t->kind == ty_overloaded) {
 1249     em.error(getPos());
 1250     em << "type of conditional expression is ambiguous";
 1251     return primError();
 1252   }
 1253 
 1254   transToType(e,t);
 1255   return t;
 1256 }
 1257 
 1258 types::ty *conditionalExp::getType(coenv &e)
 1259 {
 1260   types::ty *tt=onTrue->cgetType(e);
 1261   types::ty *ft=onFalse->cgetType(e);
 1262   if (tt->kind==ty_error || ft->kind==ty_error)
 1263     return primError();
 1264 
 1265   types::ty *t = promote(e, tt, ft);
 1266   return t ? t : primError();
 1267 }
 1268  
 1269 
 1270 void orExp::prettyprint(ostream &out, Int indent)
 1271 {
 1272   prettyname(out, "orExp", indent);
 1273 
 1274   left->prettyprint(out, indent+1);
 1275   right->prettyprint(out, indent+1);
 1276 }
 1277 
 1278 types::ty *orExp::trans(coenv &e)
 1279 {
 1280   //     a || b
 1281   // translates into
 1282   //     a ? true : b
 1283   booleanExp be(pos, true);
 1284   conditionalExp ce(pos, left, &be, right);
 1285   ce.baseTransToType(e, primBoolean());
 1286 
 1287   return getType(e);
 1288 }
 1289 
 1290 void orExp::transConditionalJump(coenv &e, bool cond, label dest)
 1291 {
 1292   if (cond == true) {
 1293     left->transConditionalJump(e, true, dest);
 1294     right->transConditionalJump(e, true, dest);
 1295   } else { /* cond == false */
 1296     label end = e.c.fwdLabel();
 1297 
 1298     left->transConditionalJump(e, true, end);
 1299     right->transConditionalJump(e, false, dest);
 1300 
 1301     e.c.defLabel(end);
 1302   }
 1303 }
 1304 
 1305 
 1306 void andExp::prettyprint(ostream &out, Int indent)
 1307 {
 1308   prettyname(out, "andExp", indent);
 1309 
 1310   left->prettyprint(out, indent+1);
 1311   right->prettyprint(out, indent+1);
 1312 }
 1313 
 1314 types::ty *andExp::trans(coenv &e)
 1315 {
 1316   //     a && b
 1317   // translates into
 1318   //     a ? b : false
 1319   booleanExp be(pos, false);
 1320   conditionalExp ce(pos, left, right, &be);
 1321   ce.baseTransToType(e, primBoolean());
 1322 
 1323   return getType(e);
 1324 }
 1325 
 1326 void andExp::transConditionalJump(coenv &e, bool cond, label dest)
 1327 {
 1328   if (cond == true) {
 1329     label end = e.c.fwdLabel();
 1330 
 1331     left->transConditionalJump(e, false, end);
 1332     right->transConditionalJump(e, true, dest);
 1333 
 1334     e.c.defLabel(end);
 1335   } else { /* cond == false */
 1336     left->transConditionalJump(e, false, dest);
 1337     right->transConditionalJump(e, false, dest);
 1338   }
 1339 }
 1340 
 1341 void joinExp::prettyprint(ostream &out, Int indent)
 1342 {
 1343   prettyname(out, "joinExp",indent);
 1344 
 1345   callee->prettyprint(out, indent+1);
 1346   args->prettyprint(out, indent+1);
 1347 }
 1348 
 1349 
 1350 void specExp::prettyprint(ostream &out, Int indent)
 1351 {
 1352   prettyindent(out,indent);
 1353   out << "specExp '" << op << "' " 
 1354       << (s==camp::OUT ? "out" :
 1355           s==camp::IN  ? "in" :
 1356           "invalid side") << '\n';
 1357 
 1358   arg->prettyprint(out, indent+1);
 1359 }
 1360 
 1361 types::ty *specExp::trans(coenv &e)
 1362 {
 1363   intExp ie(getPos(), (Int)s);
 1364   binaryExp be(getPos(), arg, op, &ie);
 1365   return be.trans(e);
 1366 }
 1367 
 1368 types::ty *specExp::getType(coenv &e)
 1369 {
 1370   intExp ie(getPos(), (Int)s);
 1371   binaryExp be(getPos(), arg, op, &ie);
 1372   return be.cgetType(e);
 1373 }
 1374 
 1375 void assignExp::prettyprint(ostream &out, Int indent)
 1376 {
 1377   prettyname(out, "assignExp",indent);
 1378 
 1379   dest->prettyprint(out, indent+1);
 1380   value->prettyprint(out, indent+1);
 1381 }
 1382 
 1383 void assignExp::transAsType(coenv &e, types::ty *target)
 1384 {
 1385 #if 0
 1386   // For left-to-right order, we have to evaluate the side-effects of the
 1387   // destination first.
 1388   exp *temp=dest->evaluate(e, target);
 1389   ultimateValue(temp)->transToType(e, target);
 1390   temp->transWrite(e, target);
 1391 #endif
 1392 
 1393   // All of the heavy work is handled by transWrite.
 1394   dest->transWrite(e, target, value);
 1395 }
 1396 
 1397 types::ty *assignExp::trans(coenv &e)
 1398 {
 1399   exp *uvalue=ultimateValue(dest);
 1400   types::ty *lt = dest->cgetType(e), *rt = uvalue->cgetType(e);
 1401 
 1402   if (lt->kind == ty_error)
 1403     return dest->trans(e);
 1404   if (rt->kind == ty_error)
 1405     return uvalue->trans(e);
 1406 
 1407   types::ty *t = e.e.castTarget(lt, rt, symbol::castsym);
 1408   if (!t) {
 1409     em.error(getPos());
 1410     em << "cannot convert '" << *rt << "' to '" << *lt << "' in assignment";
 1411     return primError();
 1412   }
 1413   else if (t->kind == ty_overloaded) {
 1414     em.error(getPos());
 1415     em << "assignment is ambiguous";
 1416     return primError();
 1417   }
 1418   else {
 1419     transAsType(e, t);
 1420     return t;
 1421   }
 1422 }
 1423 
 1424 types::ty *assignExp::getType(coenv &e)
 1425 {
 1426   types::ty *lt = dest->cgetType(e), *rt = ultimateValue(dest)->cgetType(e);
 1427   if (lt->kind==ty_error || rt->kind==ty_error)
 1428     return primError();
 1429   types::ty *t = e.e.castTarget(lt, rt, symbol::castsym);
 1430 
 1431   return t ? t : primError();
 1432 }
 1433 
 1434 
 1435 void selfExp::prettyprint(ostream &out, Int indent)
 1436 {
 1437   prettyindent(out, indent);
 1438   out << "selfExp '" << op << "'\n";
 1439 
 1440   dest->prettyprint(out, indent+1);
 1441   value->prettyprint(out, indent+1);
 1442 }
 1443 
 1444 void selfExp::transAsType(coenv &e, types::ty *target)
 1445 {
 1446   // Create a temp expression for the destination, so it is not evaluated
 1447   // twice.
 1448   exp *temp=dest->evaluate(e, target);
 1449   temp->transWrite(e, target, ultimateValue(temp));
 1450 }
 1451 
 1452 void prefixExp::prettyprint(ostream &out, Int indent)
 1453 {
 1454   prettyindent(out, indent);
 1455   out << "prefixExp '" << op << "'\n";
 1456   
 1457   dest->prettyprint(out, indent+1);
 1458 }
 1459 
 1460 types::ty *prefixExp::trans(coenv &e)
 1461 {
 1462   // Convert into the operation and the assign.
 1463   // NOTE: This can cause multiple evaluations.
 1464   intExp ie(getPos(), 1);
 1465   selfExp se(getPos(), dest, op, &ie);
 1466 
 1467   return se.trans(e);
 1468 }
 1469 
 1470 types::ty *prefixExp::getType(coenv &e)
 1471 {
 1472   // Convert into the operation and the assign.
 1473   intExp ie(getPos(), 1);
 1474   selfExp se(getPos(), dest, op, &ie);
 1475 
 1476   return se.getType(e);
 1477 }
 1478 
 1479 void postfixExp::prettyprint(ostream &out, Int indent)
 1480 {
 1481   prettyindent(out, indent);
 1482   out << "postfixExp <illegal> '" << op << "'\n";
 1483 
 1484   dest->prettyprint(out, indent+1);
 1485 }
 1486 
 1487 types::ty *postfixExp::trans(coenv &)
 1488 {
 1489   em.error(getPos());
 1490   em << "postfix expressions are not allowed";
 1491   return primError();
 1492 }
 1493 
 1494 
 1495 } // namespace absyntax
 1496