summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Robertshaw <simon@hardwired.org.uk>2012-09-23 10:39:20 (GMT)
committer Simon Robertshaw <simon@hardwired.org.uk>2012-09-23 10:39:20 (GMT)
commit1905e497442bc39cf8896e54812718064a52d621 (patch)
treeca472ca41bbe8ebfb15e71deb62670141fb4369a /src
parent644c1307124dffd13268445d0aebaed13a090c78 (diff)
downloadpowder-1905e497442bc39cf8896e54812718064a52d621.zip
powder-1905e497442bc39cf8896e54812718064a52d621.tar.gz
Macros and property setting
Diffstat (limited to 'src')
-rw-r--r--src/pim/Generator.cpp120
-rw-r--r--src/pim/Generator.h9
-rw-r--r--src/pim/Machine.cpp165
-rw-r--r--src/pim/Machine.h26
-rw-r--r--src/pim/Parser.cpp6
-rw-r--r--src/pim/Scanner.cpp15
-rw-r--r--src/pim/Token.cpp1
-rw-r--r--src/pim/Token.h1
8 files changed, 328 insertions, 15 deletions
diff --git a/src/pim/Generator.cpp b/src/pim/Generator.cpp
index 8228c1c..75b4a19 100644
--- a/src/pim/Generator.cpp
+++ b/src/pim/Generator.cpp
@@ -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()
diff --git a/src/pim/Generator.h b/src/pim/Generator.h
index 0287339..2eb1029 100644
--- a/src/pim/Generator.h
+++ b/src/pim/Generator.h
@@ -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();
diff --git a/src/pim/Machine.cpp b/src/pim/Machine.cpp
index a112363..8adb8e8 100644
--- a/src/pim/Machine.cpp
+++ b/src/pim/Machine.cpp
@@ -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;
diff --git a/src/pim/Machine.h b/src/pim/Machine.h
index a40dd51..42147dd 100644
--- a/src/pim/Machine.h
+++ b/src/pim/Machine.h
@@ -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
diff --git a/src/pim/Parser.cpp b/src/pim/Parser.cpp
index 378a252..7badae9 100644
--- a/src/pim/Parser.cpp
+++ b/src/pim/Parser.cpp
@@ -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();
diff --git a/src/pim/Scanner.cpp b/src/pim/Scanner.cpp
index 7aba994..b56d2b6 100644
--- a/src/pim/Scanner.cpp
+++ b/src/pim/Scanner.cpp
@@ -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();
diff --git a/src/pim/Token.cpp b/src/pim/Token.cpp
index 1741af0..2407167 100644
--- a/src/pim/Token.cpp
+++ b/src/pim/Token.cpp
@@ -39,6 +39,7 @@ namespace pim
"create",
"transform",
"get",
+ "RUNTIMEMACRO",
"IDENTIFIER",
",",
".",
diff --git a/src/pim/Token.h b/src/pim/Token.h
index 42e0bc2..8f19617 100644
--- a/src/pim/Token.h
+++ b/src/pim/Token.h
@@ -53,6 +53,7 @@ namespace pim
TransformSymbol,
GetSymbol,
+ RTMacro,
Identifier,
CommaSymbol,