CalcAssembler.h

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calculator/CalcAssembler.h#3 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #ifndef Fennel_CalcAssembler_Included
00024 #define Fennel_CalcAssembler_Included
00025 
00026 #include "fennel/calculator/CalcLexer.h"
00027 #include "fennel/calculator/CalcAssemblerException.h"
00028 #include "fennel/calculator/InstructionFactory.h"
00029 
00030 #include <strstream>
00031 
00032 FENNEL_BEGIN_NAMESPACE
00033 
00034 using namespace std;
00035 
00036 typedef size_t TRegisterIndex;
00037 
00038 class Calculator;
00039 class RegisterReference;
00040 class TupleDescriptor;
00041 class StoredTypeDescriptorFactory;
00042 
00043 extern int CalcYYparse (void *);
00044 
00062 class FENNEL_CALCULATOR_EXPORT CalcAssembler
00063 {
00064 public:
00065     explicit
00066     CalcAssembler(Calculator* calc) {
00067         assert(calc != NULL);
00068         mCalc = calc;
00069     }
00070 
00071     ~CalcAssembler();
00072 
00073     CalcLexer&  getLexer() {
00074         return mLexer;
00075     }
00076 
00077     int   assemble(const char* program);
00078     int   assemble();
00079 
00080     // Functions for creating objects for the calculator
00081     static TupleData*
00082     createTupleData(
00083         TupleDescriptor const& tupleDes,
00084         FixedBuffer** buf);
00085 
00086     static RegisterReference*
00087     createRegisterReference(
00088         RegisterReference::ERegisterSet setIndex,
00089         TRegisterIndex                  regIndex,
00090         StandardTypeDescriptorOrdinal   regType);
00091 
00092     static Instruction*
00093     createInstruction(
00094         string& name,
00095         vector<RegisterReference*> const &operands,
00096         CalcYYLocType& location)
00097     {
00098         Instruction* inst = NULL;
00099         try {
00100             inst = InstructionFactory::createInstruction(name, operands);
00101         } catch (FennelExcn& ex) {
00102             throw CalcAssemblerException(ex.getMessage(), location);
00103         } catch (std::exception& ex) {
00104             throw CalcAssemblerException(ex.what(), location);
00105         }
00106         if (inst == NULL) {
00107             string error;
00108             error = "Error instantiating instruction: " + name;
00109             if (operands.size() > 0) {
00110                 error += " ";
00111                 int i;
00112                 for (i = 0; i < operands.size(); i++) {
00113                     error += operands[i]->toString();
00114                     if (i + 1 < operands.size()) {
00115                         error += ", ";
00116                     }
00117                 }
00118             }
00119             throw CalcAssemblerException(error, location);
00120         }
00121         return inst;
00122     }
00123 
00124     static Instruction* createInstruction(
00125         string& name,
00126         RegisterReference* result,
00127         RegisterReference* operand1,
00128         RegisterReference* operand2,
00129         CalcYYLocType& location)
00130     {
00131         vector<RegisterReference*> operands;
00132         operands.push_back(result);
00133         operands.push_back(operand1);
00134         operands.push_back(operand2);
00135         return createInstruction(name, operands, location);
00136     }
00137 
00138 
00139     static Instruction* createInstruction(
00140         string& name,
00141         RegisterReference* result,
00142         RegisterReference* operand1,
00143         CalcYYLocType& location)
00144     {
00145         vector<RegisterReference*> operands;
00146         operands.push_back(result);
00147         operands.push_back(operand1);
00148         return createInstruction(name, operands, location);
00149     }
00150 
00151     static Instruction* createInstruction(
00152         string& name,
00153         RegisterReference* result,
00154         CalcYYLocType& location)
00155     {
00156         vector<RegisterReference*> operands;
00157         operands.push_back(result);
00158         return createInstruction(name, operands, location);
00159     }
00160 
00161     static Instruction* createInstruction(
00162         string& name,
00163         CalcYYLocType& location)
00164     {
00165         vector<RegisterReference*> operands;
00166         return createInstruction(name, operands, location);
00167     }
00168 
00169     static Instruction* createInstruction(
00170         string& name,
00171         TProgramCounter pc,
00172         CalcYYLocType& location)
00173     {
00174         return createInstruction(name, pc, NULL, location);
00175     }
00176 
00177 
00178     static Instruction* createInstruction(
00179         string& name,
00180         TProgramCounter pc,
00181         RegisterReference* operand,
00182         CalcYYLocType& location)
00183     {
00184         Instruction* inst = NULL;
00185 
00186         try {
00187             inst = InstructionFactory::createInstruction(name, pc, operand);
00188         } catch (FennelExcn& ex) {
00189             throw CalcAssemblerException(ex.getMessage(), location);
00190         } catch (std::exception& ex) {
00191             throw CalcAssemblerException(ex.what(), location);
00192         }
00193 
00194         if (inst == NULL) {
00195             stringstream errorStr("Error instantiating instruction: ");
00196             errorStr << name << " " << pc << ", ";
00197             if (operand) {
00198                 errorStr << operand->toString();
00199             }
00200             throw CalcAssemblerException(errorStr.str(), location);
00201         }
00202         return inst;
00203     }
00204 
00205     Instruction* createInstruction(
00206         string& name,
00207         string& function,
00208         vector<RegisterReference*>& operands,
00209         CalcYYLocType& location)
00210     {
00211         Instruction* inst = NULL;
00212 
00213         try {
00214             inst = InstructionFactory::createInstruction(
00215                 name, function, operands);
00216         } catch (FennelExcn& ex) {
00217             throw CalcAssemblerException(ex.getMessage(), location);
00218         } catch (std::exception& ex) {
00219             throw CalcAssemblerException(ex.what(), location);
00220         }
00221 
00222         if (inst == NULL) {
00223             InstructionSignature sig(function, operands);
00224             stringstream errorStr("Error instantiating instruction: ");
00225             errorStr << name << " ";
00226             errorStr << sig.compute();
00227             errorStr << " not registered ";
00228             throw CalcAssemblerException(errorStr.str(), location);
00229         }
00230 
00231         return inst;
00232     }
00233 
00234     static void setTupleDatum(
00235         StandardTypeDescriptorOrdinal type,
00236         TupleDatum& tupleDatum,
00237         TupleAttributeDescriptor& desc,
00238         double value);
00239     static void setTupleDatum(
00240         StandardTypeDescriptorOrdinal type,
00241         TupleDatum& tupleDatum,
00242         TupleAttributeDescriptor& desc,
00243         uint64_t value);
00244     static void setTupleDatum(
00245         StandardTypeDescriptorOrdinal type,
00246         TupleDatum& tupleDatum,
00247         TupleAttributeDescriptor& desc,
00248         int64_t value);
00249     static void setTupleDatum(
00250         StandardTypeDescriptorOrdinal type,
00251         TupleDatum& tupleDatum,
00252         TupleAttributeDescriptor& desc,
00253         string value);
00254     static void setTupleDatum(
00255         StandardTypeDescriptorOrdinal type,
00256         TupleDatum& tupleDatum,
00257         TupleAttributeDescriptor& desc,
00258         PConstBuffer buffer);
00259 
00260 protected:
00261     friend int CalcYYparse (void *);
00262 
00263     // Protected functions that are used by CalcYYparse
00264 
00266     void  init();
00267 
00276     void allocateTuples();
00277 
00286     void bindRegisters();
00287 
00302     template <typename T>
00303     void bindRegisterValue(
00304         RegisterReference::ERegisterSet setIndex,
00305         TRegisterIndex regIndex,
00306         T value)
00307     {
00308         try {
00309             StandardTypeDescriptorOrdinal regType = getRegisterType(
00310                 setIndex, regIndex);
00311             TupleData* tupleData = getTupleData(setIndex);
00312             assert(tupleData != NULL);
00313             TupleDatum& tupleDatum = (*tupleData)[regIndex];
00314             TupleDescriptor& tupleDesc = getTupleDescriptor(setIndex);
00315             setTupleDatum(regType, tupleDatum, tupleDesc[regIndex], value);
00316         } catch (CalcAssemblerException& ex) {
00317             // Just pass this exception up
00318             throw ex;
00319         } catch (FennelExcn& ex) {
00320             // Other exception - let's make the error clearer
00321             ostringstream errorStr("");
00322             errorStr << "Error binding register "
00323                      << RegisterReference::toString(setIndex, regIndex)
00324                      << ": " << ex.getMessage();
00325             throw CalcAssemblerException(
00326                 errorStr.str(), getLexer().getLocation());
00327         } catch (exception& ex) {
00328             // Other exception - let's make the error clearer
00329             ostringstream errorStr("");
00330             errorStr << "Error binding register: "
00331                      << RegisterReference::toString(setIndex, regIndex)
00332                      << ": " << ex.what();
00333             throw CalcAssemblerException(
00334                 errorStr.str(), getLexer().getLocation());
00335         }
00336     }
00337 
00353     template <typename T>
00354     void bindNextLiteral(T value)
00355     {
00356         bindRegisterValue<T>(RegisterReference::ELiteral, mLiteralIndex, value);
00357         mLiteralIndex++;
00358     }
00359 
00365     void bindLiteralDone();
00366 
00367     // CalcYYparse uses the two functions below to add a register
00368 
00373     void selectRegisterSet(RegisterReference::ERegisterSet setIndex);
00374 
00381     void addRegister(
00382         StandardTypeDescriptorOrdinal regType,
00383         uint cbStorage = 0);
00384 
00391     void addRegister(
00392         RegisterReference::ERegisterSet setIndex,
00393         StandardTypeDescriptorOrdinal regType,
00394         uint cbStorage = 0);
00395 
00396 
00397     // CalcYYparse uses this function to add a instruction
00398 
00403     void addInstruction(Instruction* inst);
00404 
00405     // Functions used by CalcYYparse to access registers and tuples
00406 
00412     TRegisterIndex getRegisterSize(RegisterReference::ERegisterSet setIndex);
00413 
00422     RegisterReference* getRegister(
00423         RegisterReference::ERegisterSet setIndex,
00424         TRegisterIndex regIndex);
00425 
00434     StandardTypeDescriptorOrdinal  getRegisterType(
00435         RegisterReference::ERegisterSet setIndex,
00436         TRegisterIndex regIndex);
00437 
00443     TupleData* getTupleData(RegisterReference::ERegisterSet setIndex);
00444 
00450     TupleDescriptor& getTupleDescriptor(
00451         RegisterReference::ERegisterSet setIndex);
00452 
00459     void checkPC(TProgramCounter pc, CalcYYLocType& loc) {
00460         assert(mCalc->mCode.size() > 0);
00461         if (pc >= static_cast<TProgramCounter>(mCalc->mCode.size())) {
00462             ostringstream errorStr("");
00463             errorStr << "Invalid PC " << pc << ": PC should be between 0 and "
00464                      << (mCalc->mCode.size() - 1);
00465             throw CalcAssemblerException(errorStr.str(), loc);
00466         }
00467     }
00468 
00476     void saveMaxPC(TProgramCounter pc)
00477     {
00478         assert(pc > 0);
00479         if (pc > mMaxPC) {
00480             mMaxPC = pc;
00481             mMaxPCLoc = getLexer().getLocation();
00482         }
00483     }
00484 
00485 protected:
00486     CalcLexer   mLexer; 
00487     Calculator* mCalc;  
00488 
00490     TupleDescriptor mRegisterSetDescriptor[RegisterReference::ELastSet];
00491 
00495     TupleData* mRegisterTupleData[RegisterReference::ELastSet];
00498     FixedBuffer* mBuffers[RegisterReference::ELastSet];
00499 
00501     StandardTypeDescriptorFactory   mTypeFactory;
00502 
00504     RegisterReference::ERegisterSet mCurrentRegSet;
00505 
00507     TRegisterIndex                  mLiteralIndex;
00508 
00510     TProgramCounter mMaxPC;
00511     CalcYYLocType   mMaxPCLoc;
00512 };
00513 
00514 FENNEL_END_NAMESPACE
00515 
00516 #endif
00517 
00518 // End CalcAssembler.h

Generated on Mon Jun 22 04:00:17 2009 for Fennel by  doxygen 1.5.1