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 //Code generator for bytecode
#include <sstream> #include <sstream>
#include <fstream>
#include "Format.h" #include "Format.h"
#include "Generator.h" #include "Generator.h"
#include "Opcodes.h" #include "Opcodes.h"
@@ -60,8 +61,27 @@ namespace pim
program.push_back(0); 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() 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) for(std::vector<Placeholder>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter)
{ {
bool found = false; bool found = false;
@@ -98,7 +118,95 @@ namespace pim
program[cPosition.first+3] = (value >> 24) & 0xFF; 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) std::string Generator::UniqueLabel(std::string prefix)
@@ -179,6 +287,12 @@ namespace pim
writeConstant(currentScope->GetDefinition(label).StackPosition); writeConstant(currentScope->GetDefinition(label).StackPosition);
} }
void Generator::RTConstant(std::string name)
{
writeOpcode(Opcode::Constant);
writeConstantMacroPlaceholder(name);
}
void Generator::Constant(std::string constant) void Generator::Constant(std::string constant)
{ {
writeOpcode(Opcode::Constant); writeOpcode(Opcode::Constant);
@@ -260,13 +374,13 @@ namespace pim
void Generator::LoadProperty(std::string property) void Generator::LoadProperty(std::string property)
{ {
writeOpcode(Opcode::LoadProperty); writeOpcode(Opcode::LoadProperty);
writeConstant(0); writeConstantPropertyPlaceholder(property);
} }
void Generator::StoreProperty(std::string property) void Generator::StoreProperty(std::string property)
{ {
writeOpcode(Opcode::StoreProperty); writeOpcode(Opcode::StoreProperty);
writeConstant(0); writeConstantPropertyPlaceholder(property);
} }
void Generator::IntegerToDecimal() void Generator::IntegerToDecimal()

View File

@@ -100,6 +100,12 @@ namespace pim
typedef std::pair<int, int*> ValuePlaceholder; typedef std::pair<int, int*> ValuePlaceholder;
std::vector<ValuePlaceholder> valuePlaceholders; 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<Label> labelPositions;
std::vector<unsigned char> program; std::vector<unsigned char> program;
@@ -110,6 +116,8 @@ namespace pim
void writeConstant(int constant); void writeConstant(int constant);
void writeConstantPlaceholder(std::string label); void writeConstantPlaceholder(std::string label);
void writeConstantPlaceholder(int * value); void writeConstantPlaceholder(int * value);
void writeConstantMacroPlaceholder(std::string macro);
void writeConstantPropertyPlaceholder(std::string property);
public: public:
Generator(); Generator();
@@ -134,6 +142,7 @@ namespace pim
void Duplicate(); void Duplicate();
void Discard(); void Discard();
void RTConstant(std::string name);
void Constant(std::string constant); void Constant(std::string constant);
void Increment(std::string constant); void Increment(std::string constant);
void Add(); 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; 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(); romSize = programData.size();
for (lastBit = 0; romSize > (1 << lastBit); lastBit++ ) { } for (lastBit = 0; romSize > (1 << lastBit); lastBit++ ) { }
@@ -37,8 +182,9 @@ namespace pim
rom = new Instruction[romSize]; rom = new Instruction[romSize];
int programPosition = 0;
int pc = 0; int pc = 0;
int programPosition = 0;
while(programPosition < programData.size()) while(programPosition < programData.size())
{ {
int argSize = 0; int argSize = 0;
@@ -46,7 +192,7 @@ namespace pim
instruction.Opcode = programData[programPosition++]; instruction.Opcode = programData[programPosition++];
if(argSize = OpcodeArgSize(instruction.Opcode)) if(argSize = OpcodeArgSize(instruction.Opcode))
{ {
if(argSize == 4) if(argSize == 4 && programPosition+3 < programData.size())
{ {
int tempInt = 0; int tempInt = 0;
tempInt |= programData[programPosition]; tempInt |= programData[programPosition];
@@ -56,12 +202,13 @@ namespace pim
std::cout << "Got integer " << tempInt << std::endl; 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; instruction.Parameter.Integer = tempInt;
programPosition += 4; programPosition += 4;
@@ -74,8 +221,6 @@ namespace pim
rom[pc++] = instruction; rom[pc++] = instruction;
} }
romSize = pc; romSize = pc;
//std::copy(programData.begin(), programData.end(), rom);
ramSize = 1024; ramSize = 1024;
ramMask = ramSize - 1; ramMask = ramSize - 1;

View File

@@ -2,6 +2,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstring>
class Simulation; class Simulation;
namespace pim namespace pim
@@ -20,6 +21,29 @@ namespace pim
int Opcode; int Opcode;
Word Parameter; 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 class VirtualMachine
{ {
@@ -42,7 +66,7 @@ namespace pim
#define CSA(argument) (*((Word*)&ram[framePointer-argument])) #define CSA(argument) (*((Word*)&ram[framePointer-argument]))
#define CS() (*((Word*)&ram[callStack])) #define CS() (*((Word*)&ram[callStack]))
#define PS() (*((Word*)&ram[programStack])) #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 programStack; //Points to the item on top of the Program Stack
int callStack; //Points to the item on top of the call 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() void Parser::variableValue()
{ {
@@ -572,6 +572,10 @@ namespace pim
} }
} }
} }
else if(accept(Token::RTMacro))
{
generator->RTConstant(variable);
}
else else
{ {
particleAction(); particleAction();

View File

@@ -86,6 +86,21 @@ namespace pim
return Token(Token::DecimalConstant, cToken, cLine); return Token(Token::DecimalConstant, cToken, cLine);
return Token(Token::IntegerConstant, 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 == '=') else if(cChar == '=')
{ {
nextCharacter(); nextCharacter();

View File

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

View File

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