Skip to content

Commit

Permalink
program code: changed to use standard vector
Browse files Browse the repository at this point in the history
moved program word and code classes to new header file
made code vector member instead of base class
added necessary code vector pass through access functions
used vector functions instead of raw memory move function
added instruction and operand program word constructors for emplace back
modified program model functions to use iterator instead of pointer
modified program model encode to use emplace back to build program line
added new header to cmake since there is no corresponding source file
(only needed to make header show up in QtCreator project file list)
  • Loading branch information
thunder422 committed Nov 15, 2014
1 parent 645eff8 commit c708042
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 122 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Expand Up @@ -180,6 +180,11 @@ add_custom_command(OUTPUT test_names.h
DEPENDS table.cpp
)

# list the header files without source files
set(ibcp_HEADERS
programcode.h
)

# list the main program sources
set(ibcp_SOURCES
basic/basic.cpp
Expand Down Expand Up @@ -301,6 +306,7 @@ add_executable(ibcp
basic/basic.h
autoenums.h
test_names.h
${ibcp_HEADERS}
${ibcp_SOURCES}
${ibcp_MOCS}
${ibcp_UI_HEADERS}
Expand Down
164 changes: 164 additions & 0 deletions programcode.h
@@ -0,0 +1,164 @@
// vim:ts=4:sw=4:
//
// Interactive BASIC Compiler Project
// File: programcode.h - program word and code class header file
// Copyright (C) 2014 Thunder422
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// For a copy of the GNU General Public License,
// see <http://www.gnu.org/licenses/>.
//
//
// Change History:
//
// 2014-11-13 initial version (from parts of programmmodel.h)

#ifndef PROGRAMCODE_H
#define PROGRAMCODE_H

#include <cstdint>
#include <vector>

#include "ibcp.h"


// class for holding and accessing a program word
// WORK moved to new programcode.h
class ProgramWord
{
public:
// instruction access functions
ProgramWord(Code code, unsigned subCode) :
// FIXME remove c-style type case
m_word((unsigned)code | (subCode & ProgramMask_SubCode)) {}

Code instructionCode() const
{
// FIXME remove c-style type case
return (Code)(m_word & ProgramMask_Code);
}
int instructionSubCode() const
{
return m_word & ProgramMask_SubCode;
}
bool instructionHasSubCode(int subCode) const
{
return (m_word & subCode) != 0;
}

// operand word access functions
ProgramWord(uint16_t operand) : m_word(operand) {}

uint16_t operand() const
{
return m_word;
}

private:
uint16_t m_word; // one program word
};


// class for holding the program code vector
class ProgramCode
{
public:
using const_iterator = std::vector<ProgramWord>::const_iterator;
using reference = std::vector<ProgramWord>::reference;

ProgramCode() {}

// code vector pass through access functions
const_iterator begin() const
{
return m_code.begin();
}
const_iterator end() const
{
return m_code.end();
}
bool empty() const
{
return m_code.empty();
}
size_t size() const
{
return m_code.size();
}
void clear()
{
m_code.clear();
}
reference operator[](size_t index)
{
return m_code[index];
}
template <typename... Args>
void emplace_back(Args&&... args)
{
m_code.emplace_back(std::forward<Args>(args)...);
}

// program line access functions
void insertLine(int offset, const ProgramCode &line)
{
if (!line.empty())
{
m_code.insert(m_code.begin() + offset, line.begin(),
line.end());
}
}

void removeLine(int offset, int oldSize)
{
if (oldSize > 0) // something to remove?
{
auto start = m_code.begin() + offset;
m_code.erase(start, start + oldSize);
}
}

void replaceLine(int offset, size_t oldSize, const ProgramCode &line)
{
if (line.empty())
{
// no new line, just remove old line
removeLine(offset, oldSize);
}
else if (line.size() >= oldSize) // new line larger or same as old?
{
// copy part of new line that will fit to replace old line
auto endCopy = std::copy(line.begin(), line.begin() + oldSize,
m_code.begin() + offset);

if (line.size() > oldSize) // more of new line?
{
// insert remaining part of new line
m_code.insert(endCopy, line.begin() + oldSize, line.end());
}
}
else // new line smaller
{
// copy new line into program
auto endCopy = std::copy(line.begin(), line.end(),
m_code.begin() + offset);

// remove extra part of old line
m_code.erase(endCopy, endCopy + oldSize - line.size());
}
}
private:
std::vector<ProgramWord> m_code; // vector of program words
};


#endif // PROGRAMCODE_H
13 changes: 6 additions & 7 deletions programmodel.cpp
Expand Up @@ -106,7 +106,7 @@ std::string ProgramModel::debugText(int lineIndex, bool fullInfo) const
oss << ']';
}

const ProgramWord *line {m_code.data() + m_lineInfo.at(lineIndex).offset};
auto line = m_code.begin() + m_lineInfo.at(lineIndex).offset;
int count {m_lineInfo.at(lineIndex).size};
for (int i {}; i < count; i++)
{
Expand Down Expand Up @@ -594,17 +594,16 @@ Status ProgramModel::errorStatus(int lineNumber) const
// function to encode a translated RPN list
ProgramCode ProgramModel::encode(const RpnList &input)
{
ProgramCode programLine(input.codeSize());
ProgramCode programLine;

for (RpnItemPtr rpnItem : input)
{
TokenPtr token {rpnItem->token()};
programLine[token->index()].setInstruction(token->code(),
token->subCodes());
programLine.emplace_back(token->code(), token->subCodes());
EncodeFunction encode {m_table.encodeFunction(token->code())};
if (encode)
{
programLine[token->index() + 1].setOperand(encode(this, token));
programLine.emplace_back(encode(this, token));
}
}
return programLine;
Expand All @@ -614,7 +613,7 @@ ProgramCode ProgramModel::encode(const RpnList &input)
// function to dereference contents of line to prepare for its removal
void ProgramModel::dereference(const LineInfo &lineInfo)
{
ProgramWord *line {m_code.data() + lineInfo.offset};
auto line = m_code.begin() + lineInfo.offset;
for (int i {}; i < lineInfo.size; i++)
{
Code code {line[i].instructionCode()};
Expand All @@ -631,7 +630,7 @@ void ProgramModel::dereference(const LineInfo &lineInfo)
RpnList ProgramModel::decode(const LineInfo &lineInfo)
{
RpnList rpnList;
ProgramWord *line {m_code.data() + lineInfo.offset};
auto line = m_code.begin() + lineInfo.offset;
for (int i {}; i < lineInfo.size; i++)
{
TokenPtr token {new Token};
Expand Down
116 changes: 1 addition & 115 deletions programmodel.h
Expand Up @@ -33,6 +33,7 @@
#include "ibcp.h"
#include "dictionary.h"
#include "errorlist.h"
#include "programcode.h"
#include "recreator.h"
#include "translator.h"
#include "basic/basic.h"
Expand All @@ -50,121 +51,6 @@ enum class Operation
};


// class for holding and accessing a program word
class ProgramWord
{
public:
// instruction access functions
Code instructionCode(void) const
{
return (Code)(m_word & ProgramMask_Code);
}
int instructionSubCode(void) const
{
return m_word & ProgramMask_SubCode;
}
bool instructionHasSubCode(int subCode) const
{
return (m_word & subCode) != 0;
}
void setInstruction(Code code, unsigned subCode)
{
m_word = (unsigned)code | (subCode & ProgramMask_SubCode);
}

// operand word access functions
unsigned short operand(void) const
{
return m_word;
}
void setOperand(unsigned short operand)
{
m_word = operand;
}

private:
unsigned short m_word; // one program word
};


// class for holding the program code
class ProgramCode : public QVector<ProgramWord>
{
public:
ProgramCode(void): QVector<ProgramWord>() { }
ProgramCode(int size): QVector<ProgramWord>(size) { }

void insertLine(int i, const ProgramCode &line)
{
if (line.size() > 0)
{
int oldSize {size()};
resize(oldSize + line.size());
ProgramWord *lineBegin = data() + i;
if (i != oldSize) // not inserting line at end?
{
// make hole in code for new line
memmove(lineBegin + line.size(), lineBegin, (oldSize - i)
* sizeof(ProgramWord));
}
// copy new line into program
memmove(lineBegin, line.data(), line.size() * sizeof(ProgramWord));
}
}

void removeLine(int i, int n)
{
if (n > 0) // something to remove?
{
remove(i, n);
}
}

void replaceLine(int i, int n, const ProgramCode &line)
{
if (line.count() == 0)
{
// no new line, just remove old line
removeLine(i, n);
return;
}
ProgramWord *offset;
if (line.count() > n) // new line larger?
{
// make program larger before moving program after line up
resize(count() - n + line.count());
offset = data() + i; // get data, resize may move data

int moveCount {count() - i - line.count()};
if (moveCount > 0) // not at end?
{
memmove(offset + line.count(), offset + n,
moveCount * sizeof(ProgramWord));
}
}
else // new line smaller or same size
{
offset = data() + i;
if (line.count() < n) // new line smaller?
{
// move program after line down before making program smaller
offset = data() + i;
int moveCount {count() - i - n};
if (moveCount > 0) // not at end?
{
memmove(offset + line.count(), offset + n,
moveCount * sizeof(ProgramWord));
}
resize(count() - n + line.count());
offset = data() + i; // get data again, resize may move data
}
}
// copy new line into program
memmove(offset, line.data(), line.count() * sizeof(ProgramWord));
}
};


// class for holding a program unit model
class ProgramModel : public QAbstractListModel
{
Expand Down

0 comments on commit c708042

Please sign in to comment.