CalcAssembler Class Reference

The CalcAssembler is responsible for taking a textual representation of a calculator program and forming a calculator. More...

#include <CalcAssembler.h>

List of all members.

Public Member Functions

 CalcAssembler (Calculator *calc)
 ~CalcAssembler ()
CalcLexergetLexer ()
int assemble (const char *program)
int assemble ()
InstructioncreateInstruction (string &name, string &function, vector< RegisterReference * > &operands, CalcYYLocType &location)

Static Public Member Functions

static TupleDatacreateTupleData (TupleDescriptor const &tupleDes, FixedBuffer **buf)
static RegisterReferencecreateRegisterReference (RegisterReference::ERegisterSet setIndex, TRegisterIndex regIndex, StandardTypeDescriptorOrdinal regType)
static InstructioncreateInstruction (string &name, vector< RegisterReference * > const &operands, CalcYYLocType &location)
static InstructioncreateInstruction (string &name, RegisterReference *result, RegisterReference *operand1, RegisterReference *operand2, CalcYYLocType &location)
static InstructioncreateInstruction (string &name, RegisterReference *result, RegisterReference *operand1, CalcYYLocType &location)
static InstructioncreateInstruction (string &name, RegisterReference *result, CalcYYLocType &location)
static InstructioncreateInstruction (string &name, CalcYYLocType &location)
static InstructioncreateInstruction (string &name, TProgramCounter pc, CalcYYLocType &location)
static InstructioncreateInstruction (string &name, TProgramCounter pc, RegisterReference *operand, CalcYYLocType &location)
static void setTupleDatum (StandardTypeDescriptorOrdinal type, TupleDatum &tupleDatum, TupleAttributeDescriptor &desc, double value)
static void setTupleDatum (StandardTypeDescriptorOrdinal type, TupleDatum &tupleDatum, TupleAttributeDescriptor &desc, uint64_t value)
static void setTupleDatum (StandardTypeDescriptorOrdinal type, TupleDatum &tupleDatum, TupleAttributeDescriptor &desc, int64_t value)
static void setTupleDatum (StandardTypeDescriptorOrdinal type, TupleDatum &tupleDatum, TupleAttributeDescriptor &desc, string value)
static void setTupleDatum (StandardTypeDescriptorOrdinal type, TupleDatum &tupleDatum, TupleAttributeDescriptor &desc, PConstBuffer buffer)

Protected Member Functions

void init ()
 Initializes the assembler.
void allocateTuples ()
 Allocates memory (creating TupleData structure) for the literal, local, and status registers.
void bindRegisters ()
 Binds registers to the calculator CalcYYparse should call this function after parsing the register definitions and literal values to bind the TupleData to the calculator registers.
template<typename T>
void bindRegisterValue (RegisterReference::ERegisterSet setIndex, TRegisterIndex regIndex, T value)
 Binds the templated value to the specified register.
template<typename T>
void bindNextLiteral (T value)
 Binds the templated value to the next literal register.
void bindLiteralDone ()
 Finishes binding literal values to registers.
void selectRegisterSet (RegisterReference::ERegisterSet setIndex)
 Sets the current register set.
void addRegister (StandardTypeDescriptorOrdinal regType, uint cbStorage=0)
 Adds a register to the current register set.
void addRegister (RegisterReference::ERegisterSet setIndex, StandardTypeDescriptorOrdinal regType, uint cbStorage=0)
 Adds a register to the specified register set.
void addInstruction (Instruction *inst)
 Adds an instruction to the calulator.
TRegisterIndex getRegisterSize (RegisterReference::ERegisterSet setIndex)
 Returns the number of registers in a register set.
RegisterReferencegetRegister (RegisterReference::ERegisterSet setIndex, TRegisterIndex regIndex)
 Returns a specified RegisterReference.
StandardTypeDescriptorOrdinal getRegisterType (RegisterReference::ERegisterSet setIndex, TRegisterIndex regIndex)
 Returns the type of register given the set index and the register index.
TupleDatagetTupleData (RegisterReference::ERegisterSet setIndex)
 Returns a pointer to the TupleData for a register set.
TupleDescriptorgetTupleDescriptor (RegisterReference::ERegisterSet setIndex)
 Returns the TupleDescriptoro for a register set.
void checkPC (TProgramCounter pc, CalcYYLocType &loc)
 Verifies that the program counter is valid.
void saveMaxPC (TProgramCounter pc)
 Saves the maximum PC.

Protected Attributes

CalcLexer mLexer
 Lexer for the assembler.
CalculatormCalc
 Calculator to be assembled.
TupleDescriptor mRegisterSetDescriptor [RegisterReference::ELastSet]
 TupleDescriptors for the register sets.
TupleDatamRegisterTupleData [RegisterReference::ELastSet]
 Pointers to the tuple data Once they have been bound to the calculator, it is the calculator's responsibility to destroy the tuple data and the buffers.
FixedBuffermBuffers [RegisterReference::ELastSet]
 Actual storage used by the CalcAssembler for the literal, local and status registers.
StandardTypeDescriptorFactory mTypeFactory
 Factory used to create TupleAttributeDescriptor.
RegisterReference::ERegisterSet mCurrentRegSet
 Register set that the assembler is currently parsing.
TRegisterIndex mLiteralIndex
 Index of the next literal register to bind.
TProgramCounter mMaxPC
 Saved information about the maximum PC.
CalcYYLocType mMaxPCLoc

Friends

int CalcYYparse (void *)


Detailed Description

The CalcAssembler is responsible for taking a textual representation of a calculator program and forming a calculator.

The CalcAssembler will do the following:

  1. Create TupleDescriptors to describe all registers
  2. Create Literal, Local, and Status Tuples and bind them to the Calculator register sets
  3. Initializes literal values in the Literal Register Set
  4. Create and insert instructions into the Calculator
  5. Verifies the format of serialized programs
  6. Performs type checking
The CalcAssembler is a temporal object that is used by the Calculator, with the Calculator responsible for the deallocation of any objects that are allocated by the CalcAssembler.

Definition at line 62 of file CalcAssembler.h.


Constructor & Destructor Documentation

CalcAssembler::CalcAssembler ( Calculator calc  )  [inline, explicit]

Definition at line 66 of file CalcAssembler.h.

00066                                     {
00067         assert(calc != NULL);
00068         mCalc = calc;
00069     }

CalcAssembler::~CalcAssembler (  ) 

Definition at line 34 of file CalcAssembler.cpp.

References RegisterReference::EFirstSet, RegisterReference::ELastSet, mBuffers, mCalc, Calculator::mRegisterSetBinding, and mRegisterTupleData.

00035 {
00036     for (uint i = RegisterReference::EFirstSet;
00037          i < RegisterReference::ELastSet;
00038          i++)
00039     {
00040         if (mCalc->mRegisterSetBinding[i] == NULL) {
00041             // We did NOT successfully bind this register set to the calculator
00042             // Will need to delete it on our own
00043             if (mBuffers[i]) {
00044                 delete[] mBuffers[i];
00045             }
00046             if (mRegisterTupleData[i]) {
00047                 delete mRegisterTupleData[i];
00048             }
00049         }
00050     }
00051 }


Member Function Documentation

CalcLexer& CalcAssembler::getLexer (  )  [inline]

Definition at line 73 of file CalcAssembler.h.

Referenced by assemble(), bindLiteralDone(), CalcYYlex(), and getRegister().

00073                            {
00074         return mLexer;
00075     }

int CalcAssembler::assemble ( const char *  program  ) 

Definition at line 70 of file CalcAssembler.cpp.

References assemble(), mLexer, and CalcAssemblerException::setCode().

Referenced by Calculator::assemble().

00071 {
00072     int res = 0;
00073     istringstream istr(program);
00074     mLexer.switch_streams(&istr, 0);
00075     try {
00076         assemble();
00077     } catch (CalcAssemblerException& ex) {
00078         ex.setCode(program);
00079         throw ex;
00080     }
00081 
00082     return res;
00083 }

int CalcAssembler::assemble (  ) 

Definition at line 85 of file CalcAssembler.cpp.

References CalcYYparse, checkPC(), getLexer(), CalcLexer::getLocation(), FennelExcn::getMessage(), mCalc, Calculator::mIsAssembling, CalcAssemblerException::mLocValid, mMaxPC, mMaxPCLoc, and CalcAssemblerException::setLocation().

Referenced by assemble().

00086 {
00087     int res = 0;
00088     try {
00089         mCalc->mIsAssembling = true;
00090         res = CalcYYparse((void*) this);
00091         if (res != 0) {
00092             throw CalcAssemblerException(
00093                 "Error assembling program", getLexer().getLocation());
00094         }
00095 
00096         // Done assembling - let's check the maximum PC (used in Jump
00097         // instruction)
00098         checkPC(mMaxPC, mMaxPCLoc);
00099     } catch (CalcAssemblerException& ex) {
00100         if (!ex.mLocValid) {
00101             ex.setLocation(getLexer().getLocation());
00102         }
00103         throw ex;
00104     } catch (FennelExcn& ex) {
00105         throw CalcAssemblerException(ex.getMessage(), getLexer().getLocation());
00106     } catch (std::exception& ex) {
00107         throw CalcAssemblerException(ex.what(), getLexer().getLocation());
00108     }
00109 
00110     return res;
00111 }

TupleData * CalcAssembler::createTupleData ( TupleDescriptor const &  tupleDes,
FixedBuffer **  buf 
) [static]

Definition at line 456 of file CalcAssembler.cpp.

References TupleAccessor::compute(), FixedBuffer, TupleAccessor::getMaxByteCount(), TupleAccessor::setCurrentTupleBuf(), TUPLE_FORMAT_ALL_FIXED, and TupleAccessor::unmarshal().

Referenced by allocateTuples(), CalcAssemblerTestCase::assemble(), and CalcAssemblerTestCase::test().

00459 {
00460     assert(buf != NULL);
00461 
00462     /* Prepare tuples - should only do this for literal/local */
00463     /* Compute memory layout and access */
00464     TupleAccessor tupleAccessor;
00465     tupleAccessor.compute(tupleDesc, TUPLE_FORMAT_ALL_FIXED);
00466 
00467     int maxByteCount = tupleAccessor.getMaxByteCount();
00468 
00469     /* Allocate memory */
00470     *buf = new FixedBuffer[maxByteCount];
00471 
00472     /* Zero the memory. */
00473     memset(*buf, 0, maxByteCount);
00474 
00475     /* Link memory - Who will delete this????? */
00476     tupleAccessor.setCurrentTupleBuf(*buf, false);
00477 
00478     /* Create Tuple Data - to be deleted by the calculator */
00479     TupleData* pTupleData = new TupleData(tupleDesc);
00480 
00481     /* Link Tuple Data with Tuple Accessor memory */
00482     tupleAccessor.unmarshal(*pTupleData);
00483     return pTupleData;
00484 }

RegisterReference * CalcAssembler::createRegisterReference ( RegisterReference::ERegisterSet  setIndex,
TRegisterIndex  regIndex,
StandardTypeDescriptorOrdinal  regType 
) [static]

Definition at line 369 of file CalcAssembler.cpp.

References STANDARD_TYPE_BINARY, STANDARD_TYPE_BOOL, STANDARD_TYPE_CHAR, STANDARD_TYPE_DOUBLE, STANDARD_TYPE_INT_16, STANDARD_TYPE_INT_32, STANDARD_TYPE_INT_64, STANDARD_TYPE_INT_8, STANDARD_TYPE_REAL, STANDARD_TYPE_UINT_16, STANDARD_TYPE_UINT_32, STANDARD_TYPE_UINT_64, STANDARD_TYPE_UINT_8, STANDARD_TYPE_VARBINARY, STANDARD_TYPE_VARCHAR, and RegisterReference::toString().

00373 {
00374     // TODO: check setIndex and regIndex
00375     RegisterReference* regRef = NULL;
00376     switch (regType) {
00377     case STANDARD_TYPE_INT_8:
00378         regRef = new RegisterRef<int8_t>(setIndex, regIndex, regType);
00379         break;
00380     case STANDARD_TYPE_UINT_8:
00381         regRef = new RegisterRef<uint8_t>(setIndex, regIndex, regType);
00382         break;
00383     case STANDARD_TYPE_INT_16:
00384         regRef = new RegisterRef<int16_t>(setIndex, regIndex, regType);
00385         break;
00386     case STANDARD_TYPE_UINT_16:
00387         regRef = new RegisterRef<uint16_t>(setIndex, regIndex, regType);
00388         break;
00389     case STANDARD_TYPE_INT_32:
00390         regRef = new RegisterRef<int32_t>(setIndex, regIndex, regType);
00391         break;
00392     case STANDARD_TYPE_UINT_32:
00393         regRef = new RegisterRef<uint32_t>(setIndex, regIndex, regType);
00394         break;
00395     case STANDARD_TYPE_INT_64:
00396         regRef = new RegisterRef<int64_t>(setIndex, regIndex, regType);
00397         break;
00398     case STANDARD_TYPE_UINT_64:
00399         regRef = new RegisterRef<uint64_t>(setIndex, regIndex, regType);
00400         break;
00401     case STANDARD_TYPE_REAL:
00402         regRef = new RegisterRef<float>(setIndex, regIndex, regType);
00403         break;
00404     case STANDARD_TYPE_DOUBLE:
00405         regRef = new RegisterRef<double>(setIndex, regIndex, regType);
00406         break;
00407     case STANDARD_TYPE_BOOL:
00408         regRef = new RegisterRef<bool>(setIndex, regIndex, regType);
00409         break;
00410     case STANDARD_TYPE_CHAR:
00411     case STANDARD_TYPE_VARCHAR:
00412         regRef = new RegisterRef<char*>(setIndex, regIndex, regType);
00413         break;
00414     case STANDARD_TYPE_BINARY:
00415     case STANDARD_TYPE_VARBINARY:
00416         regRef = new RegisterRef<int8_t*>(setIndex, regIndex, regType);
00417         break;
00418     default:
00419         ostringstream errorStr("");
00420         errorStr << "Error creating register reference for "
00421                  << RegisterReference::toString(setIndex, regIndex) << ": ";
00422         errorStr << "Unsupported register type " << regType;
00423         throw CalcAssemblerException(errorStr.str());
00424         break;
00425     }
00426     return regRef;
00427 }

static Instruction* CalcAssembler::createInstruction ( string &  name,
vector< RegisterReference * > const &  operands,
CalcYYLocType location 
) [inline, static]

Definition at line 93 of file CalcAssembler.h.

References InstructionFactory::createInstruction(), and FennelExcn::getMessage().

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     }

static Instruction* CalcAssembler::createInstruction ( string &  name,
RegisterReference result,
RegisterReference operand1,
RegisterReference operand2,
CalcYYLocType location 
) [inline, static]

Definition at line 124 of file CalcAssembler.h.

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     }

static Instruction* CalcAssembler::createInstruction ( string &  name,
RegisterReference result,
RegisterReference operand1,
CalcYYLocType location 
) [inline, static]

Definition at line 139 of file CalcAssembler.h.

00144     {
00145         vector<RegisterReference*> operands;
00146         operands.push_back(result);
00147         operands.push_back(operand1);
00148         return createInstruction(name, operands, location);
00149     }

static Instruction* CalcAssembler::createInstruction ( string &  name,
RegisterReference result,
CalcYYLocType location 
) [inline, static]

Definition at line 151 of file CalcAssembler.h.

00155     {
00156         vector<RegisterReference*> operands;
00157         operands.push_back(result);
00158         return createInstruction(name, operands, location);
00159     }

static Instruction* CalcAssembler::createInstruction ( string &  name,
CalcYYLocType location 
) [inline, static]

Definition at line 161 of file CalcAssembler.h.

00164     {
00165         vector<RegisterReference*> operands;
00166         return createInstruction(name, operands, location);
00167     }

static Instruction* CalcAssembler::createInstruction ( string &  name,
TProgramCounter  pc,
CalcYYLocType location 
) [inline, static]

Definition at line 169 of file CalcAssembler.h.

00173     {
00174         return createInstruction(name, pc, NULL, location);
00175     }

static Instruction* CalcAssembler::createInstruction ( string &  name,
TProgramCounter  pc,
RegisterReference operand,
CalcYYLocType location 
) [inline, static]

Definition at line 178 of file CalcAssembler.h.

References InstructionFactory::createInstruction(), FennelExcn::getMessage(), and RegisterReference::toString().

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     }

Instruction* CalcAssembler::createInstruction ( string &  name,
string &  function,
vector< RegisterReference * > &  operands,
CalcYYLocType location 
) [inline]

Definition at line 205 of file CalcAssembler.h.

References InstructionSignature::compute(), InstructionFactory::createInstruction(), and FennelExcn::getMessage().

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     }

void CalcAssembler::setTupleDatum ( StandardTypeDescriptorOrdinal  type,
TupleDatum tupleDatum,
TupleAttributeDescriptor desc,
double  value 
) [static]

Definition at line 122 of file CalcAssembler.cpp.

References TupleDatum::pData, STANDARD_TYPE_DOUBLE, and STANDARD_TYPE_REAL.

00127 {
00128     switch (type) {
00129     case STANDARD_TYPE_REAL:
00130 
00131         *(reinterpret_cast<float *>(const_cast<PBuffer>(tupleDatum.pData))) =
00132             boost::numeric_cast<float>(value);
00133 
00134         // Check for underflow where the value becomes 0
00135         // NOTE: Underflows that causes precision loss but does not become 0
00136         //       are ignored for now.
00137         if ((value != 0) &&
00138             (*(reinterpret_cast<float *>(const_cast<PBuffer>(tupleDatum.pData)))
00139              == 0))
00140         {
00141             throw InvalidValueException<double>(
00142                 "bad numeric cast: underflow", type, value);
00143         }
00144         break;
00145     case STANDARD_TYPE_DOUBLE:
00146         *(reinterpret_cast<double *>(const_cast<PBuffer>(tupleDatum.pData))) =
00147             boost::numeric_cast<double>(value);
00148         break;
00149     default:
00150         // Invalid real type - horrible, horrible
00151         throw InvalidValueException<double>(
00152             "Cannot assign double", type, value);
00153     }
00154 }

void CalcAssembler::setTupleDatum ( StandardTypeDescriptorOrdinal  type,
TupleDatum tupleDatum,
TupleAttributeDescriptor desc,
uint64_t  value 
) [static]

Definition at line 156 of file CalcAssembler.cpp.

References max(), TupleDatum::pData, STANDARD_TYPE_BOOL, STANDARD_TYPE_INT_16, STANDARD_TYPE_INT_32, STANDARD_TYPE_INT_64, STANDARD_TYPE_INT_8, STANDARD_TYPE_UINT_16, STANDARD_TYPE_UINT_32, STANDARD_TYPE_UINT_64, and STANDARD_TYPE_UINT_8.

00161 {
00162     switch (type) {
00163     case STANDARD_TYPE_INT_8:
00164         *(reinterpret_cast<int8_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00165             boost::numeric_cast<int8_t>(value);
00166         break;
00167     case STANDARD_TYPE_UINT_8:
00168         *(reinterpret_cast<uint8_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00169             boost::numeric_cast<uint8_t>(value);
00170         break;
00171     case STANDARD_TYPE_INT_16:
00172         *(reinterpret_cast<int16_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00173                 boost::numeric_cast<int16_t>(value);
00174         break;
00175     case STANDARD_TYPE_UINT_16:
00176         *(reinterpret_cast<uint16_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00177             boost::numeric_cast<uint16_t>(value);
00178         break;
00179     case STANDARD_TYPE_INT_32:
00180         *(reinterpret_cast<int32_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00181             boost::numeric_cast<int32_t>(value);
00182         break;
00183     case STANDARD_TYPE_UINT_32:
00184         *(reinterpret_cast<uint32_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00185             boost::numeric_cast<uint32_t>(value);
00186         break;
00187     case STANDARD_TYPE_INT_64:
00188         // Explicitly check for overflow of int64_t because the boost
00189         // boost::numeric_cast does not throw an exception in this case
00190         if (value > std::numeric_limits<int64_t>::max()) {
00191             throw InvalidValueException<uint64_t>(
00192                 "bad numeric cast: overflow", type, value);
00193         }
00194         *(reinterpret_cast<int64_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00195             boost::numeric_cast<int64_t>(value);
00196         break;
00197     case STANDARD_TYPE_UINT_64:
00198         *(reinterpret_cast<uint64_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00199             boost::numeric_cast<uint64_t>(value);
00200             break;
00201     case STANDARD_TYPE_BOOL:
00202         // Booleans are specifed as 0 or 1
00203         if (value == 1) {
00204             *(reinterpret_cast<bool *>(const_cast<PBuffer>(tupleDatum.pData))) =
00205                 true;
00206         } else if (value == 0) {
00207             *(reinterpret_cast<bool *>(const_cast<PBuffer>(tupleDatum.pData))) =
00208                 false;
00209         } else {
00210             // Invalid boolean value
00211             throw InvalidValueException<uint64_t>(
00212                 "Boolean value should be 0 or 1", type, value);
00213         }
00214         break;
00215     default:
00216         // Invalid unsigned integer type - horrible, horrible
00217         throw InvalidValueException<uint64_t>(
00218             "Cannot assign unsigned integer", type, value);
00219     }
00220 }

void CalcAssembler::setTupleDatum ( StandardTypeDescriptorOrdinal  type,
TupleDatum tupleDatum,
TupleAttributeDescriptor desc,
int64_t  value 
) [static]

Definition at line 222 of file CalcAssembler.cpp.

References TupleDatum::pData, STANDARD_TYPE_INT_16, STANDARD_TYPE_INT_32, STANDARD_TYPE_INT_64, and STANDARD_TYPE_INT_8.

00227 {
00228     switch (type) {
00229     case STANDARD_TYPE_INT_8:
00230         *(reinterpret_cast<int8_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00231             boost::numeric_cast<int8_t>(value);
00232         break;
00233     case STANDARD_TYPE_INT_16:
00234         *(reinterpret_cast<int16_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00235             boost::numeric_cast<int16_t>(value);
00236         break;
00237     case STANDARD_TYPE_INT_32:
00238         *(reinterpret_cast<int32_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00239             boost::numeric_cast<int32_t>(value);
00240         break;
00241     case STANDARD_TYPE_INT_64:
00242         *(reinterpret_cast<int64_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00243             boost::numeric_cast<int64_t>(value);
00244         break;
00245     default:
00246         throw InvalidValueException<int64_t>(
00247             "Cannot assign signed integer", type, value);
00248     }
00249 }

void CalcAssembler::setTupleDatum ( StandardTypeDescriptorOrdinal  type,
TupleDatum tupleDatum,
TupleAttributeDescriptor desc,
string  value 
) [static]

Definition at line 251 of file CalcAssembler.cpp.

References TupleDatum::cbData, TupleAttributeDescriptor::cbStorage, TupleDatum::pData, STANDARD_TYPE_BINARY, STANDARD_TYPE_CHAR, STANDARD_TYPE_VARBINARY, and STANDARD_TYPE_VARCHAR.

00256 {
00257     ostringstream errorStr;
00258     char* ptr = reinterpret_cast<char*>(const_cast<PBuffer>(tupleDatum.pData));
00259     switch (type) {
00260     case STANDARD_TYPE_CHAR:
00261     case STANDARD_TYPE_BINARY:
00262         // Fixed length storage
00263         // For fixed length arrays, cbData should be the same as cbStorage
00264         assert(tupleDatum.cbData == desc.cbStorage);
00265 
00266         // Fixed width arrays should be padded to be the specifed width
00267         // Verify that the number of bytes matches the specified width
00268         if (str.length() != tupleDatum.cbData) {
00269             ostringstream ostr("");
00270             ostr << "String length " << str.length()
00271                  << " not equal to fixed size array of length "
00272                  << tupleDatum.cbData;
00273             throw FennelExcn(ostr.str());
00274         }
00275 
00276         // Copy the string
00277         memcpy(ptr, str.data(), str.length());
00278         break;
00279 
00280     case STANDARD_TYPE_VARCHAR:
00281     case STANDARD_TYPE_VARBINARY:
00282         // Variable length storage
00283 
00284         // Verify that there the length of the string is not larger than the
00285         // maximum length
00286         if (str.length() > desc.cbStorage) {
00287             ostringstream ostr("");
00288             ostr << "String length " << str.length()
00289                  << " too long for variabled sized array of maximum length "
00290                  << desc.cbStorage;
00291             throw FennelExcn(ostr.str());
00292         }
00293 
00294         // Copy the string
00295         memcpy(ptr, str.data(), str.length());
00296         tupleDatum.cbData = str.length();
00297         break;
00298 
00299     default:
00300         throw InvalidValueException<string>("Cannot assign string", type, str);
00301     }
00302 }

void CalcAssembler::setTupleDatum ( StandardTypeDescriptorOrdinal  type,
TupleDatum tupleDatum,
TupleAttributeDescriptor desc,
PConstBuffer  buffer 
) [static]

Definition at line 113 of file CalcAssembler.cpp.

References TupleDatum::pData.

00118 {
00119     tupleDatum.pData = buffer;
00120 }

void CalcAssembler::init (  )  [protected]

Initializes the assembler.

Definition at line 53 of file CalcAssembler.cpp.

References RegisterReference::EFirstSet, RegisterReference::ELastSet, RegisterReference::EUnknown, mBuffers, mCurrentRegSet, mLiteralIndex, mMaxPC, mRegisterSetDescriptor, and mRegisterTupleData.

00054 {
00055     mCurrentRegSet = RegisterReference::EUnknown;
00056     mLiteralIndex  = 0;
00057     mMaxPC         = 0;
00058 
00059     /* Initialize tuple descriptors and tuple data */
00060     for (uint i = RegisterReference::EFirstSet;
00061          i < RegisterReference::ELastSet;
00062          i++)
00063     {
00064         mRegisterSetDescriptor[i].clear();
00065         mRegisterTupleData[i] = NULL;
00066         mBuffers[i] = NULL;
00067     }
00068 }

void CalcAssembler::allocateTuples (  )  [protected]

Allocates memory (creating TupleData structure) for the literal, local, and status registers.

CalcYYparse should call this function after parsing the register definitions and before parsing the literal values.

Note:
This function must be called before attempting to initialize the literal values.

Definition at line 487 of file CalcAssembler.cpp.

References createTupleData(), RegisterReference::EFirstSet, RegisterReference::ELastSet, RegisterReference::ELiteral, RegisterReference::ELocal, RegisterReference::EStatus, mBuffers, mRegisterSetDescriptor, and mRegisterTupleData.

00488 {
00489     /* Allocate memory for the tuples */
00490     for (uint reg = RegisterReference::EFirstSet;
00491          reg < RegisterReference::ELastSet;
00492          reg++)
00493     {
00494         /* Verify that tuples have not already been allocated */
00495         assert(mRegisterTupleData[reg] == NULL);
00496         assert(mBuffers[reg] == NULL);
00497 
00498         if (reg == RegisterReference::ELiteral ||
00499             reg == RegisterReference::EStatus ||
00500             reg == RegisterReference::ELocal)
00501         {
00502             /* Allocate tuple for literal/status/local registers */
00503             mRegisterTupleData[reg] = createTupleData(
00504                 mRegisterSetDescriptor[reg],
00505                 &mBuffers[reg]);
00506         }
00507 
00508         /* Do not need to create input/output tuple data */
00509     }
00510 }

void CalcAssembler::bindRegisters (  )  [protected]

Binds registers to the calculator CalcYYparse should call this function after parsing the register definitions and literal values to bind the TupleData to the calculator registers.

Note:
This function must be called after all tuples have been allocated and literal values initialized

Definition at line 512 of file CalcAssembler.cpp.

References Calculator::bind(), RegisterReference::EInput, RegisterReference::ELiteral, RegisterReference::ELocal, RegisterReference::EOutput, RegisterReference::EStatus, getTupleData(), getTupleDescriptor(), mBuffers, Calculator::mBuffers, mCalc, and Calculator::mRegisterSetDescriptor.

00513 {
00514     /* Bind registers to calculator */
00515     RegisterReference::ERegisterSet reg;
00516 
00517     /* Bind literal */
00518     reg = RegisterReference::ELiteral;
00519     mCalc->mBuffers.push_back(mBuffers[reg]);
00520     mCalc->bind(reg, getTupleData(reg), getTupleDescriptor(reg));
00521 
00522     /* Bind status */
00523     reg = RegisterReference::EStatus;
00524     mCalc->mBuffers.push_back(mBuffers[reg]);
00525     mCalc->bind(reg, getTupleData(reg), getTupleDescriptor(reg));
00526 
00527     /* Bind local */
00528     reg = RegisterReference::ELocal;
00529     mCalc->mBuffers.push_back(mBuffers[reg]);
00530     mCalc->bind(reg, getTupleData(reg), getTupleDescriptor(reg));
00531 
00532     /* Do not create input/output tuple data - we still need to bind
00533        the tuple descriptor */
00534     reg = RegisterReference::EInput;
00535     mCalc->mRegisterSetDescriptor[reg] =
00536         new TupleDescriptor(getTupleDescriptor(reg));
00537 
00538     reg = RegisterReference::EOutput;
00539     mCalc->mRegisterSetDescriptor[reg] =
00540         new TupleDescriptor(getTupleDescriptor(reg));
00541 }

template<typename T>
void CalcAssembler::bindRegisterValue ( RegisterReference::ERegisterSet  setIndex,
TRegisterIndex  regIndex,
value 
) [inline, protected]

Binds the templated value to the specified register.

A CalcAssemblerException with the location of the current token is thrown if there is an error binding the value to the register.

Parameters:
setIndex Register set index
regIndex Register index
value Value to bind to the register
Exceptions:
CalcAssemblerException 
Note:
The assembler is only responsible for binding literal values. This function is used by bindNextLiteral for binding literal values. There should be no reason to use this function directly.
See also:
bindNextLiteral

Definition at line 303 of file CalcAssembler.h.

References FennelExcn::getMessage(), and RegisterReference::toString().

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     }

template<typename T>
void CalcAssembler::bindNextLiteral ( value  )  [inline, protected]

Binds the templated value to the next literal register.

A CalcAssemblerException with the location of the current token is thrown if there is an error binding the value to the register.

Parameters:
value Value to bind to the register
Exceptions:
CalcAssemblerException 
Note:
CalcYYparse calls this function to bind individual literal value as they are parsed one by one. Before calling this function, bindRegisters() should be called to allocate memory for the TupleData and bind them to the registers. After all literal values are bound, bindLiteralsDone() should be called to check that all literal registers have been initialized.
See also:
bindLiteralsDone()

bindRegisters()

Definition at line 354 of file CalcAssembler.h.

References RegisterReference::ELiteral.

00355     {
00356         bindRegisterValue<T>(RegisterReference::ELiteral, mLiteralIndex, value);
00357         mLiteralIndex++;
00358     }

void CalcAssembler::bindLiteralDone (  )  [protected]

Finishes binding literal values to registers.

This function should be called by CalcYYparse after all parsing literal values to check that all literal registers have been initialized.

Definition at line 304 of file CalcAssembler.cpp.

References RegisterReference::ELiteral, getLexer(), CalcLexer::getLocation(), getRegisterSize(), and mLiteralIndex.

00305 {
00306     // We are done with binding literals
00307     // Check that all literals have been a value
00308     TRegisterIndex regSize = getRegisterSize(RegisterReference::ELiteral);
00309     if (mLiteralIndex != regSize) {
00310         ostringstream errorStr("");
00311         errorStr << "Error binding literals: " << regSize
00312                  << " literal registers, only " << mLiteralIndex
00313                  << " registers bound";
00314         throw CalcAssemblerException(errorStr.str(), getLexer().getLocation());
00315     }
00316 }

void CalcAssembler::selectRegisterSet ( RegisterReference::ERegisterSet  setIndex  )  [protected]

Sets the current register set.

Parameters:
setIndex Register set index

Definition at line 318 of file CalcAssembler.cpp.

References mCurrentRegSet.

00319 {
00320     mCurrentRegSet = setIndex;
00321 }

void CalcAssembler::addRegister ( StandardTypeDescriptorOrdinal  regType,
uint  cbStorage = 0 
) [protected]

Adds a register to the current register set.

Parameters:
regType type of the register to add
cbStorage space to allocate for the register (used for arrays)
Note:
Use selectRegisterSet to set the current register set

void CalcAssembler::addRegister ( RegisterReference::ERegisterSet  setIndex,
StandardTypeDescriptorOrdinal  regType,
uint  cbStorage = 0 
) [protected]

Adds a register to the specified register set.

Parameters:
setIndex Register set index
regType type of the register to add
cbStorage space to allocate for the register (used for arrays)

void CalcAssembler::addInstruction ( Instruction inst  )  [protected]

Adds an instruction to the calulator.

Parameters:
inst Instruction to add

Definition at line 543 of file CalcAssembler.cpp.

References Calculator::appendInstruction(), and mCalc.

00544 {
00545     assert(inst != NULL);
00546     mCalc->appendInstruction(inst);
00547 }

TRegisterIndex CalcAssembler::getRegisterSize ( RegisterReference::ERegisterSet  setIndex  )  [protected]

Returns the number of registers in a register set.

Parameters:
setIndex Register set index
Returns:
Number of registers in the register set

Definition at line 348 of file CalcAssembler.cpp.

References RegisterReference::ELastSet, mCalc, and Calculator::mRegisterRef.

Referenced by bindLiteralDone(), and getRegister().

00350 {
00351     assert(setIndex < RegisterReference::ELastSet);
00352     return mCalc->mRegisterRef[setIndex].size();
00353 }

RegisterReference * CalcAssembler::getRegister ( RegisterReference::ERegisterSet  setIndex,
TRegisterIndex  regIndex 
) [protected]

Returns a specified RegisterReference.

Parameters:
setIndex Register set index
regIndex Register index
Returns:
RegisterReference pointer
Exceptions:
FennelExcn Exception indicating the register index is out of bounds

Definition at line 332 of file CalcAssembler.cpp.

References RegisterReference::ELastSet, getLexer(), CalcLexer::getLocation(), getRegisterSize(), RegisterReference::getSetName(), mCalc, and Calculator::mRegisterRef.

Referenced by getRegisterType().

00335 {
00336     assert(setIndex < RegisterReference::ELastSet);
00337     TRegisterIndex size = getRegisterSize(setIndex);
00338     if (regIndex >= size) {
00339         ostringstream errorStr("");
00340         errorStr << "Register index " << regIndex << " out of bounds.";
00341         errorStr << " Register set " << RegisterReference::getSetName(setIndex)
00342                  << " has " << size << " registers.";
00343         throw CalcAssemblerException(errorStr.str(), getLexer().getLocation());
00344     }
00345     return mCalc->mRegisterRef[setIndex][regIndex];
00346 }

StandardTypeDescriptorOrdinal CalcAssembler::getRegisterType ( RegisterReference::ERegisterSet  setIndex,
TRegisterIndex  regIndex 
) [protected]

Returns the type of register given the set index and the register index.

Parameters:
setIndex Register set index
regIndex Register index
Returns:
Type of the register
Exceptions:
FennelExcn Exception indicating the register index is out of bounds

Definition at line 323 of file CalcAssembler.cpp.

References getRegister(), and RegisterReference::type().

00326 {
00327     RegisterReference* regRef = getRegister(setIndex, regIndex);
00328     assert(regRef != NULL);
00329     return regRef->type();
00330 }

TupleData * CalcAssembler::getTupleData ( RegisterReference::ERegisterSet  setIndex  )  [protected]

Returns a pointer to the TupleData for a register set.

Parameters:
setIndex Register set index
Returns:
Pointer to the TupleData

Definition at line 355 of file CalcAssembler.cpp.

References RegisterReference::ELastSet, and mRegisterTupleData.

Referenced by bindRegisters().

00356 {
00357     assert(setIndex < RegisterReference::ELastSet);
00358     return mRegisterTupleData[setIndex];
00359 }

TupleDescriptor & CalcAssembler::getTupleDescriptor ( RegisterReference::ERegisterSet  setIndex  )  [protected]

Returns the TupleDescriptoro for a register set.

Parameters:
setIndex Register set index
Returns:
TupleDescriptor

Definition at line 361 of file CalcAssembler.cpp.

References RegisterReference::ELastSet, and mRegisterSetDescriptor.

Referenced by bindRegisters().

00363 {
00364     assert(setIndex < RegisterReference::ELastSet);
00365     return mRegisterSetDescriptor[setIndex];
00366 }

void CalcAssembler::checkPC ( TProgramCounter  pc,
CalcYYLocType loc 
) [inline, protected]

Verifies that the program counter is valid.

Parameters:
pc the program counter
loc 
Exceptions:
CalcAssemblerException Exception indicating that the PC is invalid

Definition at line 459 of file CalcAssembler.h.

Referenced by assemble().

00459                                                          {
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     }

void CalcAssembler::saveMaxPC ( TProgramCounter  pc  )  [inline, protected]

Saves the maximum PC.

It is impossible to check the PC until we have assembled the entire program and it is too much trouble to keep track of every PC to see if they are valid or not. Instead, we will just keep track of the maximum PC, and if it is valid, then all PCs should be valid. If it is not, then we will just report on that PC.

Definition at line 476 of file CalcAssembler.h.

00477     {
00478         assert(pc > 0);
00479         if (pc > mMaxPC) {
00480             mMaxPC = pc;
00481             mMaxPCLoc = getLexer().getLocation();
00482         }
00483     }


Friends And Related Function Documentation

int CalcYYparse ( void *   )  [friend]

Referenced by assemble().


Member Data Documentation

CalcLexer CalcAssembler::mLexer [protected]

Lexer for the assembler.

Definition at line 486 of file CalcAssembler.h.

Referenced by assemble().

Calculator* CalcAssembler::mCalc [protected]

Calculator to be assembled.

Definition at line 487 of file CalcAssembler.h.

Referenced by addInstruction(), assemble(), bindRegisters(), getRegister(), getRegisterSize(), and ~CalcAssembler().

TupleDescriptor CalcAssembler::mRegisterSetDescriptor[RegisterReference::ELastSet] [protected]

TupleDescriptors for the register sets.

Definition at line 490 of file CalcAssembler.h.

Referenced by allocateTuples(), getTupleDescriptor(), and init().

TupleData* CalcAssembler::mRegisterTupleData[RegisterReference::ELastSet] [protected]

Pointers to the tuple data Once they have been bound to the calculator, it is the calculator's responsibility to destroy the tuple data and the buffers.

Definition at line 495 of file CalcAssembler.h.

Referenced by allocateTuples(), getTupleData(), init(), and ~CalcAssembler().

FixedBuffer* CalcAssembler::mBuffers[RegisterReference::ELastSet] [protected]

Actual storage used by the CalcAssembler for the literal, local and status registers.

Definition at line 498 of file CalcAssembler.h.

Referenced by allocateTuples(), bindRegisters(), init(), and ~CalcAssembler().

StandardTypeDescriptorFactory CalcAssembler::mTypeFactory [protected]

Factory used to create TupleAttributeDescriptor.

Definition at line 501 of file CalcAssembler.h.

RegisterReference::ERegisterSet CalcAssembler::mCurrentRegSet [protected]

Register set that the assembler is currently parsing.

Definition at line 504 of file CalcAssembler.h.

Referenced by init(), and selectRegisterSet().

TRegisterIndex CalcAssembler::mLiteralIndex [protected]

Index of the next literal register to bind.

Definition at line 507 of file CalcAssembler.h.

Referenced by bindLiteralDone(), and init().

TProgramCounter CalcAssembler::mMaxPC [protected]

Saved information about the maximum PC.

Definition at line 510 of file CalcAssembler.h.

Referenced by assemble(), and init().

CalcYYLocType CalcAssembler::mMaxPCLoc [protected]

Definition at line 511 of file CalcAssembler.h.

Referenced by assemble().


The documentation for this class was generated from the following files:
Generated on Mon Jun 22 04:00:27 2009 for Fennel by  doxygen 1.5.1