diff options
| author | Simon 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) |
| commit | 1905e497442bc39cf8896e54812718064a52d621 (patch) | |
| tree | ca472ca41bbe8ebfb15e71deb62670141fb4369a /src | |
| parent | 644c1307124dffd13268445d0aebaed13a090c78 (diff) | |
| download | powder-1905e497442bc39cf8896e54812718064a52d621.zip powder-1905e497442bc39cf8896e54812718064a52d621.tar.gz | |
Macros and property setting
Diffstat (limited to 'src')
| -rw-r--r-- | src/pim/Generator.cpp | 120 | ||||
| -rw-r--r-- | src/pim/Generator.h | 9 | ||||
| -rw-r--r-- | src/pim/Machine.cpp | 165 | ||||
| -rw-r--r-- | src/pim/Machine.h | 26 | ||||
| -rw-r--r-- | src/pim/Parser.cpp | 6 | ||||
| -rw-r--r-- | src/pim/Scanner.cpp | 15 | ||||
| -rw-r--r-- | src/pim/Token.cpp | 1 | ||||
| -rw-r--r-- | src/pim/Token.h | 1 |
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, |
