Macros and property setting

This commit is contained in:
Simon Robertshaw 2012-09-23 11:39:20 +01:00
parent 644c130712
commit 1905e49744
8 changed files with 328 additions and 15 deletions

View File

@ -1,5 +1,6 @@
//Code generator for bytecode
#include <sstream>
#include <fstream>
#include "Format.h"
#include "Generator.h"
#include "Opcodes.h"
@ -60,8 +61,27 @@ namespace pim
program.push_back(0);
}
void Generator::writeConstantPropertyPlaceholder(std::string property)
{
propertyPlaceholders.push_back(PropertyPlaceholder(program.size(), property));
program.push_back(0);
program.push_back(0);
program.push_back(0);
program.push_back(0);
}
void Generator::writeConstantMacroPlaceholder(std::string macro)
{
macroPlaceholders.push_back(MacroPlaceholder(program.size(), macro));
program.push_back(0);
program.push_back(0);
program.push_back(0);
program.push_back(0);
}
std::vector<unsigned char> Generator::Finish()
{
//All compile time labels, macros, etc
for(std::vector<Placeholder>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter)
{
bool found = false;
@ -98,7 +118,95 @@ namespace pim
program[cPosition.first+3] = (value >> 24) & 0xFF;
}
return program;
//Build file
int macroSizePos, propSizePos, codeSizePos, macroSize = 0, propSize = 0, codeSize = program.size();
std::vector<unsigned char> file;
file.push_back('P');
file.push_back('V');
file.push_back('M');
file.push_back('1');
macroSizePos = file.size();
file.push_back(0);
file.push_back(0);
file.push_back(0);
file.push_back(0);
propSizePos = file.size();
file.push_back(0);
file.push_back(0);
file.push_back(0);
file.push_back(0);
codeSizePos = file.size();
file.push_back(0);
file.push_back(0);
file.push_back(0);
file.push_back(0);
//Macros
for(std::vector<MacroPlaceholder>::iterator iter = macroPlaceholders.begin(), end = macroPlaceholders.end(); iter != end; ++iter)
{
MacroPlaceholder cPosition = *iter;
int position = cPosition.first;
file.push_back(position & 0xFF);
file.push_back((position >> 8) & 0xFF);
file.push_back((position >> 16) & 0xFF);
file.push_back((position >> 24) & 0xFF);
macroSize += 4;
file.push_back(cPosition.second.length());
macroSize += 1;
file.insert(file.end(), cPosition.second.begin(), cPosition.second.end());
macroSize += cPosition.second.length();
}
file[macroSizePos] = macroSize & 0xFF;
file[macroSizePos+1] = (macroSize >> 8) & 0xFF;
file[macroSizePos+2] = (macroSize >> 16) & 0xFF;
file[macroSizePos+3] = (macroSize >> 24) & 0xFF;
//Macros
for(std::vector<PropertyPlaceholder>::iterator iter = propertyPlaceholders.begin(), end = propertyPlaceholders.end(); iter != end; ++iter)
{
PropertyPlaceholder cPosition = *iter;
int position = cPosition.first;
file.push_back(position & 0xFF);
file.push_back((position >> 8) & 0xFF);
file.push_back((position >> 16) & 0xFF);
file.push_back((position >> 24) & 0xFF);
propSize += 4;
file.push_back(cPosition.second.length());
propSize += 1;
file.insert(file.end(), cPosition.second.begin(), cPosition.second.end());
propSize += cPosition.second.length();
}
file[propSizePos] = propSize & 0xFF;
file[propSizePos+1] = (propSize >> 8) & 0xFF;
file[propSizePos+2] = (propSize >> 16) & 0xFF;
file[propSizePos+3] = (propSize >> 24) & 0xFF;
file.insert(file.end(), program.begin(), program.end());
file[codeSizePos] = codeSize & 0xFF;
file[codeSizePos+1] = (codeSize >> 8) & 0xFF;
file[codeSizePos+2] = (codeSize >> 16) & 0xFF;
file[codeSizePos+3] = (codeSize >> 24) & 0xFF;
std::ofstream newFile("test.pvm");
for(std::vector<unsigned char>::iterator iter = file.begin(), end = file.end(); iter != end; ++iter)
{
newFile.put(*iter);
}
newFile.close();
return file;
}
std::string Generator::UniqueLabel(std::string prefix)
@ -179,6 +287,12 @@ namespace pim
writeConstant(currentScope->GetDefinition(label).StackPosition);
}
void Generator::RTConstant(std::string name)
{
writeOpcode(Opcode::Constant);
writeConstantMacroPlaceholder(name);
}
void Generator::Constant(std::string constant)
{
writeOpcode(Opcode::Constant);
@ -260,13 +374,13 @@ namespace pim
void Generator::LoadProperty(std::string property)
{
writeOpcode(Opcode::LoadProperty);
writeConstant(0);
writeConstantPropertyPlaceholder(property);
}
void Generator::StoreProperty(std::string property)
{
writeOpcode(Opcode::StoreProperty);
writeConstant(0);
writeConstantPropertyPlaceholder(property);
}
void Generator::IntegerToDecimal()

View File

@ -100,6 +100,12 @@ namespace pim
typedef std::pair<int, int*> ValuePlaceholder;
std::vector<ValuePlaceholder> valuePlaceholders;
typedef std::pair<int, std::string> PropertyPlaceholder;
std::vector<PropertyPlaceholder> propertyPlaceholders;
typedef std::pair<int, std::string> MacroPlaceholder;
std::vector<MacroPlaceholder> macroPlaceholders;
std::vector<Label> labelPositions;
std::vector<unsigned char> program;
@ -110,6 +116,8 @@ namespace pim
void writeConstant(int constant);
void writeConstantPlaceholder(std::string label);
void writeConstantPlaceholder(int * value);
void writeConstantMacroPlaceholder(std::string macro);
void writeConstantPropertyPlaceholder(std::string property);
public:
Generator();
@ -134,6 +142,7 @@ namespace pim
void Duplicate();
void Discard();
void RTConstant(std::string name);
void Constant(std::string constant);
void Increment(std::string constant);
void Add();

View File

@ -25,10 +25,155 @@ namespace pim
}
void VirtualMachine::LoadProgram(std::vector<unsigned char> programData)
void VirtualMachine::LoadProgram(std::vector<unsigned char> fileData)
{
int lastBit = 0;
if(!(fileData[0] == 'P' && fileData[1] == 'V' && fileData[2] == 'M' && fileData[3] == '1' && fileData.size() >= 16))
{
throw InvalidProgramException();
}
int macroSize = 0, propSize = 0, codeSize = 0;
macroSize = fileData[4];
macroSize |= fileData[5] << 8;
macroSize |= fileData[6] << 16;
macroSize |= fileData[7] << 24;
propSize = fileData[8];
propSize |= fileData[9] << 8;
propSize |= fileData[10] << 16;
propSize |= fileData[11] << 24;
codeSize = fileData[12];
codeSize |= fileData[13] << 8;
codeSize |= fileData[14] << 16;
codeSize |= fileData[15] << 24;
if(fileData.size() < 16 + macroSize + propSize + codeSize)
{
throw InvalidProgramException();
}
//std::vector<std::pair<int, int> > insertions;
int macroOffset = 16;
int propOffset = macroOffset+macroSize;
int codeOffset = propOffset+propSize;
int filePosition = macroOffset;
while(filePosition + 4 < macroSize + macroOffset)
{
std::string macro;
int macroPosition;
int macroValue;
macroPosition = fileData[filePosition++];
macroPosition |= fileData[filePosition++] << 8;
macroPosition |= fileData[filePosition++] << 16;
macroPosition |= fileData[filePosition++] << 24;
int stringLength = fileData[filePosition++];
if(filePosition + stringLength > macroSize + macroOffset)
{
throw InvalidProgramException();
}
macro.insert(macro.begin(), fileData.begin()+filePosition, fileData.begin()+filePosition+stringLength);
filePosition += stringLength;
bool resolved = false;
for(int i = 0; i < PT_NUM; i++)
{
if(sim->elements[i].Enabled && sim->elements[i].Identifier == macro)
{
macroValue = i;
resolved = true;
}
}
if(!resolved)
{
throw UnresolvedValueException(macro);
}
if(macroPosition + 3 >= codeSize)
{
throw InvalidProgramException();
}
std::cout << "Macro insertion [" << macro << "] at " << macroPosition << " with " << macroValue << std::endl;
fileData[codeOffset+macroPosition] = macroValue & 0xFF;
fileData[codeOffset+macroPosition+1] = (macroValue >> 8) & 0xFF;
fileData[codeOffset+macroPosition+2] = (macroValue >> 16) & 0xFF;
fileData[codeOffset+macroPosition+3] = (macroValue >> 24) & 0xFF;
//insertions.push_back(std::pair<int, int>(macroPosition, macroValue));
}
filePosition = propOffset;
while(filePosition + 4 < propSize + propOffset)
{
std::string prop;
int propPosition;
int propValue;
propPosition = fileData[filePosition++];
propPosition |= fileData[filePosition++] << 8;
propPosition |= fileData[filePosition++] << 16;
propPosition |= fileData[filePosition++] << 24;
int stringLength = fileData[filePosition++];
if(filePosition + stringLength > propSize + propOffset)
{
throw InvalidProgramException();
}
prop.insert(prop.begin(), fileData.begin()+filePosition, fileData.begin()+filePosition+stringLength);
filePosition += stringLength;
bool resolved = false;
std::vector<StructProperty> properties = Particle::GetProperties();
for(std::vector<StructProperty>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter)
{
StructProperty property = *iter;
std::cout << property.Offset << std::endl;
if(property.Name == prop &&
(property.Type == StructProperty::ParticleType ||
property.Type == StructProperty::Colour ||
property.Type == StructProperty::Integer ||
property.Type == StructProperty::UInteger ||
property.Type == StructProperty::Float)
)
{
propValue = property.Offset;
resolved = true;
break;
}
}
if(!resolved)
{
throw UnresolvedValueException(prop);
}
if(propPosition + 3 >= codeSize)
{
throw InvalidProgramException();
}
std::cout << "Property insertion [" << prop << "] at " << propPosition << " with " << propValue << std::endl;
fileData[codeOffset+propPosition] = propValue & 0xFF;
fileData[codeOffset+propPosition+1] = (propValue >> 8) & 0xFF;
fileData[codeOffset+propPosition+2] = (propValue >> 16) & 0xFF;
fileData[codeOffset+propPosition+3] = (propValue >> 24) & 0xFF;
//insertions.push_back(std::pair<int, int>(macroPosition, macroValue));
}
std::vector<unsigned char> programData;
programData.insert(programData.begin(), fileData.begin()+codeOffset, fileData.begin()+codeOffset+codeSize);
romSize = programData.size();
for (lastBit = 0; romSize > (1 << lastBit); lastBit++ ) { }
@ -37,8 +182,9 @@ namespace pim
rom = new Instruction[romSize];
int programPosition = 0;
int pc = 0;
int programPosition = 0;
while(programPosition < programData.size())
{
int argSize = 0;
@ -46,7 +192,7 @@ namespace pim
instruction.Opcode = programData[programPosition++];
if(argSize = OpcodeArgSize(instruction.Opcode))
{
if(argSize == 4)
if(argSize == 4 && programPosition+3 < programData.size())
{
int tempInt = 0;
tempInt |= programData[programPosition];
@ -56,12 +202,13 @@ namespace pim
std::cout << "Got integer " << tempInt << std::endl;
//std::cout << "Got byte " << (int)(programData[programPosition]) << std::endl;
//std::cout << "Got byte " << (int)(programData[programPosition+1]) << std::endl;
//std::cout << "Got byte " << (int)(programData[programPosition+2]) << std::endl;
//std::cout << "Got byte " << (int)(programData[programPosition+3]) << std::endl;
//*(int*)&rom[programPosition] = tempInt;
if(instruction.Opcode == Opcode::LoadProperty || instruction.Opcode == Opcode::StoreProperty)
{
if(tempInt > offsetof(Particle, dcolour))
throw InvalidProgramException();
}
instruction.Parameter.Integer = tempInt;
programPosition += 4;
@ -74,8 +221,6 @@ namespace pim
rom[pc++] = instruction;
}
romSize = pc;
//std::copy(programData.begin(), programData.end(), rom);
ramSize = 1024;
ramMask = ramSize - 1;

View File

@ -2,6 +2,7 @@
#include <vector>
#include <string>
#include <cstring>
class Simulation;
namespace pim
@ -20,6 +21,29 @@ namespace pim
int Opcode;
Word Parameter;
};
class InvalidProgramException: public std::exception
{
public:
InvalidProgramException() { }
const char * what() const throw()
{
return "Invalid program";
}
~InvalidProgramException() throw() {};
};
class UnresolvedValueException: public std::exception
{
char * error;
public:
UnresolvedValueException(std::string value) {
error = strdup(std::string("Unresolved value: " + value).c_str());
}
const char * what() const throw()
{
return error;
}
~UnresolvedValueException() throw() {};
};
class VirtualMachine
{
@ -42,7 +66,7 @@ namespace pim
#define CSA(argument) (*((Word*)&ram[framePointer-argument]))
#define CS() (*((Word*)&ram[callStack]))
#define PS() (*((Word*)&ram[programStack]))
#define PPROP(index, property) (*((Word*)(&sim->parts[(index)]+property)))
#define PPROP(index, property) (*((Word*)(((char*)&sim->parts[(index)])+property)))
int programStack; //Points to the item on top of the Program Stack
int callStack; //Points to the item on top of the call stack

View File

@ -545,7 +545,7 @@ namespace pim
}
/*
<variable value> ::= <function call> | identifier | identifier.property | <particle action>
<variable value> ::= <function call> | identifier | identifier.property | rtmacro | <particle action>
*/
void Parser::variableValue()
{
@ -572,6 +572,10 @@ namespace pim
}
}
}
else if(accept(Token::RTMacro))
{
generator->RTConstant(variable);
}
else
{
particleAction();

View File

@ -86,6 +86,21 @@ namespace pim
return Token(Token::DecimalConstant, cToken, cLine);
return Token(Token::IntegerConstant, cToken, cLine);
}
else if(cChar == '[')
{
cToken.clear();
nextCharacter();
while(std::isalpha(cChar) || std::isdigit(cChar) || cChar == '_' || cChar == '-')
{
cToken.push_back(cChar);
nextCharacter();
}
nextCharacter();
std::transform(cToken.begin(), cToken.end(), cToken.begin(), ::toupper);
return Token(Token::RTMacro, cToken, cLine);
}
else if(cChar == '=')
{
nextCharacter();

View File

@ -39,6 +39,7 @@ namespace pim
"create",
"transform",
"get",
"RUNTIMEMACRO",
"IDENTIFIER",
",",
".",

View File

@ -53,6 +53,7 @@ namespace pim
TransformSymbol,
GetSymbol,
RTMacro,
Identifier,
CommaSymbol,