Macros and property setting
This commit is contained in:
parent
644c130712
commit
1905e49744
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -39,6 +39,7 @@ namespace pim
|
||||
"create",
|
||||
"transform",
|
||||
"get",
|
||||
"RUNTIMEMACRO",
|
||||
"IDENTIFIER",
|
||||
",",
|
||||
".",
|
||||
|
@ -53,6 +53,7 @@ namespace pim
|
||||
TransformSymbol,
|
||||
GetSymbol,
|
||||
|
||||
RTMacro,
|
||||
Identifier,
|
||||
|
||||
CommaSymbol,
|
||||
|
Reference in New Issue
Block a user