ucexpr.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2000 The Exult Team
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 
00029 
00030 #include <stdio.h>
00031 #include "ucexpr.h"
00032 #include "ucsym.h"
00033 #include "utils.h"
00034 #include "opcodes.h"
00035 #include "ucfun.h"
00036 
00037 /*
00038  *  Default.  Just push the one value.
00039  *
00040  *  Output: # pushed
00041  */
00042 
00043 int Uc_expression::gen_values
00044   (
00045   vector<char>& out
00046   )
00047   {
00048   gen_value(out);     // Gen. result on stack.
00049   return 1;
00050   }
00051 
00052 /*
00053  *  Default jmp-if-false generation.
00054  *
00055  *  Output: offset where offset is stored.
00056  */
00057 
00058 int Uc_expression::gen_jmp_if_false
00059   (
00060   vector<char>& out,
00061   int offset      // Offset to jmp (relative).
00062   )
00063   {
00064   gen_value(out);     // Gen. result on stack.
00065   out.push_back((char) UC_JNE);   // Pop and jmp if false.
00066   Write2(out, offset);
00067   return out.size() - 2;
00068   }
00069 
00070 /*
00071  *  Default assignment generation.
00072  */
00073 
00074 void Uc_expression::gen_assign
00075   (
00076   vector<char>& out
00077   )
00078   {
00079   error("Can't assign to this expression");
00080   }
00081 
00082 /*
00083  *  Need a variable whose value is this expression.
00084  */
00085 
00086 Uc_var_symbol *Uc_expression::need_var
00087   (
00088   vector<char>& out,
00089   Uc_function *fun
00090   )
00091   {
00092   static int cnt = 0;
00093   char buf[50];
00094   sprintf(buf, "_tmpval_%d", cnt++);
00095           // Create a 'tmp' variable.
00096   Uc_var_symbol *var = fun->add_symbol(buf);
00097   if (!var)
00098     return 0;   // Shouldn't happen.  Err. reported.
00099   gen_value(out);     // Want to assign this value to it.
00100   var->gen_assign(out);
00101   return var;
00102   }
00103 
00104 /*
00105  *  Evaluate constant.
00106  *
00107  *  Output: true if successful, with result returned in 'val'.
00108  */
00109 
00110 bool Uc_expression::eval_const
00111   (
00112   int& val      // Value returned here.
00113   )
00114   {
00115   val = 0;
00116   error("Integer constant expected.");
00117   return false;
00118   }
00119 
00120 /*
00121  *  Generate code to evaluate expression and leave result on stack.
00122  */
00123 
00124 void Uc_var_expression::gen_value
00125   (
00126   vector<char>& out
00127   )
00128   {
00129   char buf[150];
00130   if (!var->gen_value(out))
00131     {
00132     sprintf(buf, "Can't use value of '%s'", var->get_name());
00133     error(buf);
00134     }
00135   }
00136 
00137 /*
00138  *  Generate assignment to this variable.
00139  */
00140 
00141 void Uc_var_expression::gen_assign
00142   (
00143   vector<char>& out
00144   )
00145   {
00146   char buf[150];
00147   if (!var->gen_assign(out))
00148     {
00149     sprintf(buf, "Can't assign to '%s'", var->get_name());
00150     error(buf);
00151     }
00152   }
00153 
00154 /*
00155  *  Generate code to evaluate expression and leave result on stack.
00156  */
00157 
00158 void Uc_arrayelem_expression::gen_value
00159   (
00160   vector<char>& out
00161   )
00162   {
00163   if (!index || !array)
00164     return;
00165   index->gen_value(out);    // Want index on stack.
00166   out.push_back((char) UC_AIDX);  // Opcode, var #.
00167   Write2(out, array->get_offset());
00168   }
00169 
00170 /*
00171  *  Generate assignment to this variable.
00172  */
00173 
00174 void Uc_arrayelem_expression::gen_assign
00175   (
00176   vector<char>& out
00177   )
00178   {
00179   if (!index || !array)
00180     return;
00181   index->gen_value(out);    // Want index on stack.
00182   out.push_back((char) UC_POPARR);  // Opcode, var #.
00183   Write2(out, array->get_offset());
00184   }
00185 
00186 /*
00187  *  Generate code to evaluate expression and leave result on stack.
00188  */
00189 
00190 void Uc_flag_expression::gen_value
00191   (
00192   vector<char>& out
00193   )
00194   {
00195   out.push_back((char) UC_PUSHF); // Opcode, flag #.
00196   Write2(out, index);
00197   }
00198 
00199 /*
00200  *  Generate assignment to this variable.
00201  */
00202 
00203 void Uc_flag_expression::gen_assign
00204   (
00205   vector<char>& out
00206   )
00207   {
00208   out.push_back((char) UC_POPF);
00209   Write2(out, index);
00210   }
00211 
00212 /*
00213  *  Get offset in function's text_data.
00214  *
00215  *  Output: Offset.
00216  */
00217 
00218 int Uc_var_expression::get_string_offset
00219   (
00220   )
00221   { 
00222   return var->get_string_offset(); 
00223   }
00224 
00225 /*
00226  *  Generate code to evaluate expression and leave result on stack.
00227  */
00228 
00229 void Uc_binary_expression::gen_value
00230   (
00231   vector<char>& out
00232   )
00233   {
00234   left->gen_value(out);   // First the left.
00235   right->gen_value(out);    // Then the right.
00236   out.push_back((char) opcode);
00237   }
00238 
00239 /*
00240  *  Evaluate constant.
00241  *
00242  *  Output: true if successful, with result returned in 'val'.
00243  */
00244 
00245 bool Uc_binary_expression::eval_const
00246   (
00247   int& val      // Value returned here.
00248   )
00249   {
00250   int val1, val2;     // Get each side.
00251   if (!left->eval_const(val1) || !right->eval_const(val2))
00252     return false;
00253   switch (opcode)
00254     {
00255   case UC_ADD:  val = val1 + val2; return true;
00256   case UC_SUB:  val = val1 - val2; return true;
00257   case UC_MUL:  val = val1*val2; return true;
00258   case UC_DIV:
00259     if (!val2)
00260       {
00261       error("Division by 0");
00262       return false;
00263       }
00264     val = val1/val2;
00265     return true;
00266     }
00267   val = 0;
00268   error("This operation not supported for integer constants");
00269   return false;
00270   }
00271 
00272 /*
00273  *  Generate code to evaluate expression and leave result on stack.
00274  */
00275 
00276 void Uc_unary_expression::gen_value
00277   (
00278   vector<char>& out
00279   )
00280   {
00281   operand->gen_value(out);
00282   out.push_back((char) opcode);
00283   }
00284 
00285 /*
00286  *  Can't use this expression just anywhere.
00287  */
00288 
00289 void Uc_response_expression::gen_value
00290   (
00291   vector<char>& out
00292   )
00293   {
00294   error("Must use UcResponse in 'if (UcResponse == ...)'");
00295   }
00296 
00297 /*
00298  *  Jmp-if-false generation for getting conversation response & comparing
00299  *  to a string or strings.
00300  *
00301  *  Output: offset where offset is stored.
00302  */
00303 
00304 int Uc_response_expression::gen_jmp_if_false
00305   (
00306   vector<char>& out,
00307   int offset      // Offset to jmp (relative).
00308   )
00309   {
00310           // Push string(s) on stack.
00311   int cnt = operand->gen_values(out);
00312   out.push_back((char) UC_CMPS);
00313   Write2(out, cnt);   // # strings on stack.
00314   Write2(out, offset);    // Offset to jmp if false.
00315   return out.size() - 2;
00316   }
00317 
00318 /*
00319  *  Generate code to evaluate expression and leave result on stack.
00320  */
00321 
00322 void Uc_int_expression::gen_value
00323   (
00324   vector<char>& out
00325   )
00326   {
00327   out.push_back((char) UC_PUSHI);
00328   Write2(out, value);
00329   }
00330 
00331 /*
00332  *  Evaluate constant.
00333  *
00334  *  Output: true if successful, with result returned in 'val'.
00335  */
00336 
00337 bool Uc_int_expression::eval_const
00338   (
00339   int& val      // Value returned here.
00340   )
00341   {
00342   val = value;
00343   return true;
00344   }
00345 
00346 /*
00347  *  Generate code to evaluate expression and leave result on stack.
00348  */
00349 
00350 void Uc_bool_expression::gen_value
00351   (
00352   vector<char>& out
00353   )
00354   {
00355   if (tf)
00356     out.push_back((char) UC_PUSHTRUE);
00357   else
00358     out.push_back((char) UC_PUSHFALSE);
00359   }
00360 
00361 /*
00362  *  Generate code to evaluate expression and leave result on stack.
00363  */
00364 
00365 void Uc_event_expression::gen_value
00366   (
00367   vector<char>& out
00368   )
00369   {
00370   out.push_back((char) UC_PUSHEVENTID);
00371   }
00372 
00373 /*
00374  *  Generate assignment to this variable.
00375  */
00376 
00377 void Uc_event_expression::gen_assign
00378   (
00379   vector<char>& out
00380   )
00381   {
00382   out.push_back((char) UC_POPEVENTID);
00383   }
00384 
00385 /*
00386  *  Generate code to evaluate expression and leave result on stack.
00387  */
00388 
00389 void Uc_item_expression::gen_value
00390   (
00391   vector<char>& out
00392   )
00393   {
00394   out.push_back((char) UC_PUSHITEMREF);
00395   }
00396 
00397 /*
00398  *  Generate code to evaluate expression and leave result on stack.
00399  */
00400 
00401 void Uc_string_expression::gen_value
00402   (
00403   vector<char>& out
00404   )
00405   {
00406   out.push_back((char) UC_PUSHS);
00407   Write2(out, offset);
00408   }
00409 
00410 /*
00411  *  Generate code to evaluate expression and leave result on stack.
00412  */
00413 
00414 void Uc_string_prefix_expression::gen_value
00415   (
00416   vector<char>& out
00417   )
00418   {
00419   out.push_back((char) UC_PUSHS);
00420   Write2(out, get_string_offset());
00421   }
00422 
00423 /*
00424  *  Get offset in function's text_data.
00425  *
00426  *  Output: Offset.
00427  */
00428 
00429 int Uc_string_prefix_expression::get_string_offset
00430   (
00431   )
00432   { 
00433   if (offset < 0)     // First time?
00434           // Look up & print errors.
00435     offset = fun->find_string_prefix(*this, prefix.c_str());
00436   return offset;
00437   }
00438 
00439 /*
00440  *  Delete a list of expressions.
00441  */
00442 
00443 Uc_array_expression::~Uc_array_expression
00444   (
00445   )
00446   {
00447   for (std::vector<Uc_expression *>::iterator it = exprs.begin(); 
00448             it != exprs.end(); it++)
00449     delete (*it);
00450   }
00451 
00452 /*
00453  *  Concatenate another expression, or its values if an array, onto this.
00454  *  If the expression is an array, it's deleted after its elements are
00455  *  taken.
00456  */
00457 
00458 void Uc_array_expression::concat
00459   (
00460   Uc_expression *e
00461   )
00462   {
00463   Uc_array_expression *arr = dynamic_cast<Uc_array_expression *> (e);
00464   if (!arr)
00465     add(e);     // Singleton?  Just add it.
00466   else
00467     {
00468     for (std::vector<Uc_expression *>::iterator it = 
00469       arr->exprs.begin(); it != arr->exprs.end(); it++)
00470       add(*it);
00471     arr->exprs.clear(); // Don't want to delete elements.
00472     delete arr;   // But this array is history.
00473     }
00474   }
00475 
00476 /*
00477  *  Generate code to evaluate expression and leave result on stack.
00478  */
00479 
00480 void Uc_array_expression::gen_value
00481   (
00482   vector<char>& out
00483   )
00484   {
00485   int actual = Uc_array_expression::gen_values(out);
00486   out.push_back((char) UC_ARRC);
00487   Write2(out, actual);
00488   }
00489 
00490 /*
00491  *  Push all values onto the stack.
00492  *
00493  *  Output: # pushed
00494  */
00495 
00496 int Uc_array_expression::gen_values
00497   (
00498   vector<char>& out
00499   )
00500   {
00501   int actual = 0;     // (Just to be safe.)
00502           // Push backwards, so #0 pops first.
00503   for (std::vector<Uc_expression *>::reverse_iterator it = 
00504         exprs.rbegin(); it != exprs.rend(); it++)
00505     {
00506     Uc_expression *expr = *it;
00507     if (expr)
00508       {
00509       actual++;
00510       expr->gen_value(out);
00511       }
00512     }
00513   return actual;
00514   }
00515 
00516 /*
00517  *  Generate code to evaluate expression and leave result on stack.
00518  */
00519 
00520 void Uc_call_expression::gen_value
00521   (
00522   vector<char>& out
00523   )
00524   {
00525   if (!sym)
00526     return;     // Already failed once.
00527   if (!sym->gen_call(out, function, original, itemref,  
00528               parms, return_value))
00529     {
00530     char buf[150];
00531     sprintf(buf, "'%s' isn't a function or intrinsic",
00532             sym->get_name());
00533     sym = 0;    // Avoid repeating error if in loop.
00534     error(buf);
00535     }
00536   }

Generated on Mon Jul 9 14:42:51 2007 for ExultEngine by  doxygen 1.5.1