This commit is contained in:
Simon Robertshaw 2013-02-01 20:25:48 +00:00
commit 1e535a160d
12 changed files with 247 additions and 40 deletions

40
src/pim/Exceptions.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <cstring>
#include <string>
#include "Token.h"
namespace pim
{
namespace compiler {
class ParserExpectException: public std::exception
{
char * error;
public:
ParserExpectException(Token token, int expectingSymbol) {
error = strdup(std::string("Expecting " + Token::SymbolNames[expectingSymbol] + " got " + token.Source).c_str());
}
ParserExpectException(Token token, std::string expectingString) {
error = strdup(std::string("Expecting " + expectingString + " got " + token.Source).c_str());
}
const char * what() const throw()
{
return error;
}
~ParserExpectException() throw() {};
};
class TypeException: public std::exception
{
char * error;
public:
TypeException(int type, int expectingType) {
error = strdup(std::string("Expecting a particular type, got a different type").c_str());
}
const char * what() const throw()
{
return error;
}
~TypeException() throw() {};
};
}
}

View File

@ -4,11 +4,13 @@
#include "Format.h" #include "Format.h"
#include "Generator.h" #include "Generator.h"
#include "Opcodes.h" #include "Opcodes.h"
#include "Exceptions.h"
namespace pim namespace pim
{ {
namespace compiler namespace compiler
{ {
Generator::Generator() : Generator::Generator() :
typeStack(),
output(std::cout), output(std::cout),
labelCounter(0), labelCounter(0),
programCounter(0) programCounter(0)
@ -16,6 +18,10 @@ namespace pim
} }
Generator::~Generator()
{
}
void Generator::defineLabel(std::string label) void Generator::defineLabel(std::string label)
{ {
Label newLabel; Label newLabel;
@ -313,6 +319,47 @@ namespace pim
variableType = type; variableType = type;
} }
void Generator::PushType(int type)
{
typeStack.push(type);
}
void Generator::pushType(int type)
{
typeStack.push(type);
}
void Generator::popType(int count)
{
while(count--)
{
typeStack.pop();
}
}
void Generator::AssureType(int type)
{
int otherType = typeStack.top();
if(otherType != type)
{
if(otherType == DataType::Integer && type == DataType::Float)
{
ToFloat();
}
else if(otherType == DataType::Float && type == DataType::Integer)
{
ToInteger();
}
}
}
void Generator::ForceType(int type)
{
if(typeStack.top() != type)
throw new TypeException(typeStack.top(), type);
}
void Generator::ScopeVariable(std::string label) void Generator::ScopeVariable(std::string label)
{ {
currentScope->Definitions.push_back(Definition(label, variableType, currentScope->LocalFrameSize, currentScope)); currentScope->Definitions.push_back(Definition(label, variableType, currentScope->LocalFrameSize, currentScope));
@ -329,8 +376,11 @@ namespace pim
void Generator::LoadVariable(std::string label) void Generator::LoadVariable(std::string label)
{ {
writeOpcode(Opcode::Load);
Definition d = currentScope->GetDefinition(label); Definition d = currentScope->GetDefinition(label);
pushType(d.Type);
writeOpcode(Opcode::Load);
writeConstant(d.StackPosition+(currentScope->FrameSize-d.MyScope->FrameSize)); writeConstant(d.StackPosition+(currentScope->FrameSize-d.MyScope->FrameSize));
output << "load " << label << std::endl; output << "load " << label << std::endl;
@ -338,8 +388,12 @@ namespace pim
void Generator::StoreVariable(std::string label) void Generator::StoreVariable(std::string label)
{ {
writeOpcode(Opcode::Store);
Definition d = currentScope->GetDefinition(label); Definition d = currentScope->GetDefinition(label);
AssureType(d.Type);
popType(1);
writeOpcode(Opcode::Store);
writeConstant(d.StackPosition+(currentScope->FrameSize-d.MyScope->FrameSize)); writeConstant(d.StackPosition+(currentScope->FrameSize-d.MyScope->FrameSize));
//writeConstantPlaceholderOffset(currentScope->GetDefinition(label).StackPosition, &(currentScope->OldFrameSize)); //writeConstantPlaceholderOffset(currentScope->GetDefinition(label).StackPosition, &(currentScope->OldFrameSize));
//writeConstant(currentScope->GetDefinition(label).StackPosition); //writeConstant(currentScope->GetDefinition(label).StackPosition);
@ -349,6 +403,7 @@ namespace pim
void Generator::RTConstant(std::string name) void Generator::RTConstant(std::string name)
{ {
pushType(DataType::Integer);
writeOpcode(Opcode::Constant); writeOpcode(Opcode::Constant);
writeConstantMacroPlaceholder(name); writeConstantMacroPlaceholder(name);
@ -357,6 +412,7 @@ namespace pim
void Generator::Constant(std::string constant) void Generator::Constant(std::string constant)
{ {
pushType(DataType::Integer);
writeOpcode(Opcode::Constant); writeOpcode(Opcode::Constant);
writeConstant(constant); writeConstant(constant);
@ -374,6 +430,7 @@ namespace pim
void Generator::Discard() void Generator::Discard()
{ {
popType(1);
writeOpcode(Opcode::Discard); writeOpcode(Opcode::Discard);
output << "discard" << std::endl; output << "discard" << std::endl;
@ -381,6 +438,7 @@ namespace pim
void Generator::Duplicate() void Generator::Duplicate()
{ {
pushType(typeStack.top());
writeOpcode(Opcode::Duplicate); writeOpcode(Opcode::Duplicate);
output << "duplicate" << std::endl; output << "duplicate" << std::endl;
@ -388,6 +446,8 @@ namespace pim
void Generator::Add() void Generator::Add()
{ {
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Add); writeOpcode(Opcode::Add);
output << "add" << std::endl; output << "add" << std::endl;
@ -395,6 +455,8 @@ namespace pim
void Generator::Subtract() void Generator::Subtract()
{ {
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Subtract); writeOpcode(Opcode::Subtract);
output << "sub" << std::endl; output << "sub" << std::endl;
@ -402,13 +464,36 @@ namespace pim
void Generator::Multiply() void Generator::Multiply()
{ {
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Multiply); writeOpcode(Opcode::Multiply);
output << "mul" << std::endl; output << "mul" << std::endl;
} }
void Generator::ToInteger()
{
popType(1);
pushType(DataType::Integer);
writeOpcode(Opcode::ToInteger);
output << "ftoi" << std::endl;
}
void Generator::ToFloat()
{
popType(1);
pushType(DataType::Float);
writeOpcode(Opcode::ToFloat);
output << "itof" << std::endl;
}
void Generator::Divide() void Generator::Divide()
{ {
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Divide); writeOpcode(Opcode::Divide);
output << "div" << std::endl; output << "div" << std::endl;
@ -416,6 +501,8 @@ namespace pim
void Generator::Modulus() void Generator::Modulus()
{ {
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Modulus); writeOpcode(Opcode::Modulus);
output << "add" << std::endl; output << "add" << std::endl;
@ -444,6 +531,8 @@ namespace pim
void Generator::GetParticle() void Generator::GetParticle()
{ {
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Get); writeOpcode(Opcode::Get);
output << "getpart" << std::endl; output << "getpart" << std::endl;
@ -451,6 +540,9 @@ namespace pim
void Generator::GetPosition() void Generator::GetPosition()
{ {
popType(1);
pushType(DataType::Integer);
pushType(DataType::Integer);
writeOpcode(Opcode::Position); writeOpcode(Opcode::Position);
output << "getpos" << std::endl; output << "getpos" << std::endl;
@ -458,6 +550,7 @@ namespace pim
void Generator::KillParticle() void Generator::KillParticle()
{ {
popType(1);
writeOpcode(Opcode::Kill); writeOpcode(Opcode::Kill);
output << "kill" << std::endl; output << "kill" << std::endl;
@ -465,6 +558,8 @@ namespace pim
void Generator::LoadProperty(std::string property) void Generator::LoadProperty(std::string property)
{ {
popType(1);
pushType(DataType::Integer);
writeOpcode(Opcode::LoadProperty); writeOpcode(Opcode::LoadProperty);
writeConstantPropertyPlaceholder(property); writeConstantPropertyPlaceholder(property);
@ -473,25 +568,19 @@ namespace pim
void Generator::StoreProperty(std::string property) void Generator::StoreProperty(std::string property)
{ {
ForceType(DataType::Integer); //Ensure particle ID is an integer
popType(1); //Use particle ID
popType(1);
writeOpcode(Opcode::StoreProperty); writeOpcode(Opcode::StoreProperty);
writeConstantPropertyPlaceholder(property); writeConstantPropertyPlaceholder(property);
output << "storeprop " << property << std::endl; output << "storeprop " << property << std::endl;
} }
void Generator::IntegerToDecimal()
{
}
void Generator::DecimalToInteger()
{
}
void Generator::JumpEqual(std::string label) void Generator::JumpEqual(std::string label)
{ {
popType(2);
writeOpcode(Opcode::JumpEqual); writeOpcode(Opcode::JumpEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
@ -500,6 +589,7 @@ namespace pim
void Generator::JumpNotEqual(std::string label) void Generator::JumpNotEqual(std::string label)
{ {
popType(2);
writeOpcode(Opcode::JumpNotEqual); writeOpcode(Opcode::JumpNotEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
@ -508,6 +598,7 @@ namespace pim
void Generator::JumpGreater(std::string label) void Generator::JumpGreater(std::string label)
{ {
popType(2);
writeOpcode(Opcode::JumpGreater); writeOpcode(Opcode::JumpGreater);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
@ -516,6 +607,7 @@ namespace pim
void Generator::JumpGreaterEqual(std::string label) void Generator::JumpGreaterEqual(std::string label)
{ {
popType(2);
writeOpcode(Opcode::JumpGreaterEqual); writeOpcode(Opcode::JumpGreaterEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
@ -524,6 +616,7 @@ namespace pim
void Generator::JumpLess(std::string label) void Generator::JumpLess(std::string label)
{ {
popType(2);
writeOpcode(Opcode::JumpLess); writeOpcode(Opcode::JumpLess);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
@ -532,6 +625,7 @@ namespace pim
void Generator::JumpLessEqual(std::string label) void Generator::JumpLessEqual(std::string label)
{ {
popType(2);
writeOpcode(Opcode::JumpLessEqual); writeOpcode(Opcode::JumpLessEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
@ -540,6 +634,7 @@ namespace pim
void Generator::Jump(std::string label) void Generator::Jump(std::string label)
{ {
popType(2);
writeOpcode(Opcode::Jump); writeOpcode(Opcode::Jump);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);

View File

@ -5,6 +5,7 @@
#include <stack> #include <stack>
#include <iostream> #include <iostream>
#include "Token.h" #include "Token.h"
#include "Types.h"
namespace pim namespace pim
{ {
namespace compiler namespace compiler
@ -36,10 +37,6 @@ namespace pim
} }
~SymbolNotFoundException() throw() {}; ~SymbolNotFoundException() throw() {};
}; };
class Type
{
enum { Integer = Token::IntegerSymbol, Decimal = Token::DecimalSymbol };
};
class Scope; class Scope;
class Definition class Definition
{ {
@ -93,6 +90,7 @@ namespace pim
class Generator class Generator
{ {
int variableType; int variableType;
std::stack<int> typeStack;
std::stack<Scope*> scopes; std::stack<Scope*> scopes;
Scope * currentScope; Scope * currentScope;
std::ostream & output; std::ostream & output;
@ -118,6 +116,9 @@ namespace pim
std::vector<unsigned char> program; std::vector<unsigned char> program;
void pushType(int type);
void popType(int count);
void defineLabel(std::string label); void defineLabel(std::string label);
void writeOpcode(int opcode); void writeOpcode(int opcode);
void writeConstant(std::string constant); void writeConstant(std::string constant);
@ -130,11 +131,15 @@ namespace pim
public: public:
Generator(); Generator();
virtual ~Generator();
std::vector<unsigned char> Finish(); std::vector<unsigned char> Finish();
std::string UniqueLabel(std::string prefix); std::string UniqueLabel(std::string prefix);
void AssureType(int type);
void ForceType(int type);
void PushScope(std::string label); void PushScope(std::string label);
void PushLocalScope(std::string label); void PushLocalScope(std::string label);
void LocalEnter(); void LocalEnter();
@ -145,6 +150,7 @@ namespace pim
void ScopeVariableType(int type); void ScopeVariableType(int type);
void ScopeVariable(std::string label); void ScopeVariable(std::string label);
void PushType(int type);
void PushVariableAddress(std::string label); void PushVariableAddress(std::string label);
// void Store(); // void Store();
void LoadVariable(std::string label); void LoadVariable(std::string label);
@ -161,6 +167,8 @@ namespace pim
void Divide(); void Divide();
void Modulus(); void Modulus();
void Negate(); void Negate();
void ToInteger();
void ToFloat();
void TransformParticle(); void TransformParticle();
void CreateParticle(); void CreateParticle();
@ -170,9 +178,6 @@ namespace pim
void LoadProperty(std::string property); void LoadProperty(std::string property);
void StoreProperty(std::string property); void StoreProperty(std::string property);
void IntegerToDecimal();
void DecimalToInteger();
void JumpEqual(std::string label); void JumpEqual(std::string label);
void JumpNotEqual(std::string label); void JumpNotEqual(std::string label);
void JumpGreater(std::string label); void JumpGreater(std::string label);

View File

@ -4,6 +4,7 @@
#include <fstream> #include <fstream>
#include "Machine.h" #include "Machine.h"
#include "Opcodes.h" #include "Opcodes.h"
#include "Types.h"
#include "simulation/Simulation.h" #include "simulation/Simulation.h"
#include "X86Native.h" #include "X86Native.h"
namespace pim namespace pim
@ -269,6 +270,8 @@ namespace pim
case Opcode::Get: case Opcode::Get:
case Opcode::Position: case Opcode::Position:
case Opcode::Kill: case Opcode::Kill:
case Opcode::ToFloat:
case Opcode::ToInteger:
return 0; return 0;
} }
} }

View File

@ -2,6 +2,7 @@ namespace pim
{ {
struct Opcode struct Opcode
{ {
public:
enum enum
{ {
#define OPDEF(name) name, #define OPDEF(name) name,

View File

@ -1,4 +1,6 @@
OPDEF(Load) OPDEF(Load)
OPDEF(ToFloat)
OPDEF(ToInteger)
OPDEF(Store) OPDEF(Store)
OPDEF(Constant) OPDEF(Constant)
OPDEF(Increment) OPDEF(Increment)

View File

@ -1,6 +1,10 @@
//Syntax analyser //Syntax analyser
#include "Parser.h" #include "Parser.h"
#include "Format.h" #include "Format.h"
#include "Types.h"
#include "Exceptions.h"
#include "simulation/Particle.h"
#include "simulation/StructProperty.h"
namespace pim namespace pim
{ {
namespace compiler namespace compiler
@ -106,7 +110,18 @@ namespace pim
*/ */
void Parser::argument() void Parser::argument()
{ {
generator->ScopeVariableType(token.Symbol); int type;
switch(token.Symbol)
{
case Token::DecimalConstant:
type = DataType::Float;
break;
case Token::IntegerConstant:
case Token::ParticleConstant:
type = DataType::Integer;
break;
}
generator->ScopeVariableType(type);
if(!accept(Token::IntegerSymbol)) if(!accept(Token::IntegerSymbol))
if(!accept(Token::DecimalSymbol)) if(!accept(Token::DecimalSymbol))
if(!accept(Token::ParticleSymbol)) if(!accept(Token::ParticleSymbol))
@ -130,7 +145,18 @@ namespace pim
*/ */
void Parser::declaration() void Parser::declaration()
{ {
generator->ScopeVariableType(token.Symbol); int type;
switch(token.Symbol)
{
case Token::DecimalConstant:
type = DataType::Float;
break;
case Token::IntegerConstant:
case Token::ParticleConstant:
type = DataType::Integer;
break;
}
generator->ScopeVariableType(type);
if(!accept(Token::IntegerSymbol)) if(!accept(Token::IntegerSymbol))
if(!accept(Token::DecimalSymbol)) if(!accept(Token::DecimalSymbol))
if(!accept(Token::ParticleSymbol)) if(!accept(Token::ParticleSymbol))
@ -296,7 +322,7 @@ namespace pim
generator->PushLocalScope(loopLabel+"Start"); generator->PushLocalScope(loopLabel+"Start");
neighbourVariable = token.Source; neighbourVariable = token.Source;
expect(Token::Identifier); expect(Token::Identifier);
generator->ScopeVariableType(Token::IntegerConstant); generator->ScopeVariableType(DataType::Integer);
generator->ScopeVariable(neighbourVariable); generator->ScopeVariable(neighbourVariable);
generator->ScopeVariable(xVar); generator->ScopeVariable(xVar);
generator->ScopeVariable(yVar); generator->ScopeVariable(yVar);
@ -471,6 +497,22 @@ namespace pim
expect(Token::Identifier); expect(Token::Identifier);
expect(Token::AssignSymbol); expect(Token::AssignSymbol);
expression(); expression();
int t2;
StructProperty::PropertyType t = Particle::GetProperty(property).Type;
switch(t){
case StructProperty::ParticleType:
case StructProperty::Colour:
case StructProperty::Integer:
case StructProperty::UInteger:
t2 = DataType::Integer;
break;
case StructProperty::Float:
t2 = DataType::Float;
break;
}
generator->AssureType(t2);
generator->LoadVariable(variable); generator->LoadVariable(variable);
generator->StoreProperty(property); generator->StoreProperty(property);
} }

View File

@ -10,22 +10,6 @@ namespace pim
{ {
namespace compiler namespace compiler
{ {
class ParserExpectException: public std::exception
{
char * error;
public:
ParserExpectException(Token token, int expectingSymbol) {
error = strdup(std::string("Expecting " + Token::SymbolNames[expectingSymbol] + " got " + token.Source).c_str());
}
ParserExpectException(Token token, std::string expectingString) {
error = strdup(std::string("Expecting " + expectingString + " got " + token.Source).c_str());
}
const char * what() const throw()
{
return error;
}
~ParserExpectException() throw() {};
};
class Parser class Parser
{ {
std::stringstream & source; std::stringstream & source;

13
src/pim/Types.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
namespace pim
{
struct DataType
{
public:
enum
{
Integer,
Float
};
};
}

View File

@ -11,9 +11,10 @@ namespace pim
nativeRom.clear(); nativeRom.clear();
unsigned char * esi = new unsigned char[1024*1024];//malloc(1024*1024); unsigned char * esi = new unsigned char[1024*1024];//malloc(1024*1024);
esi += 512; esi += 512;
//int * esi = malloc(1024*1024);
emit("BE"); //mov esi, machineStack emit("BE"); //mov esi, machineStack
emit((intptr_t)esi); emit((intptr_t)esi);
while(programCounter < romSize) while(programCounter < romSize)
{ {
Word argument = rom[programCounter].Parameter; Word argument = rom[programCounter].Parameter;
@ -215,6 +216,14 @@ namespace pim
emit("83 C6 08"); //add esi, 8 emit("83 C6 08"); //add esi, 8
} }
break; break;
case Opcode::ToFloat:
emit("DB 06"); //fild [esi]
emit("D9 1E"); //fstp [esi]
break;
case Opcode::ToInteger:
emit("D9 06"); //fld [esi]
emit("DB 1E"); //fistp [esi]
break;
case Opcode::JumpEqual: case Opcode::JumpEqual:
emit("83 C6 08"); //add esi, 8 emit("83 C6 08"); //add esi, 8
emit("8B 46 FC"); //mov eax, [esi-4] emit("8B 46 FC"); //mov eax, [esi-4]

View File

@ -25,3 +25,15 @@ std::vector<StructProperty> Particle::GetProperties()
properties.push_back(StructProperty("dcolour", StructProperty::UInteger, offsetof(Particle, dcolour))); properties.push_back(StructProperty("dcolour", StructProperty::UInteger, offsetof(Particle, dcolour)));
return properties; return properties;
} }
StructProperty Particle::GetProperty(std::string propertyName)
{
std::vector<StructProperty> types = GetProperties();
for(std::vector<StructProperty>::iterator iter = types.begin(), end = types.end(); iter != end; ++iter)
{
if((*iter).Name == propertyName)
return *iter;
}
return StructProperty("unknown", StructProperty::Float, 0);
}

View File

@ -26,6 +26,7 @@ struct Particle
/** Returns a list of properties, their type and offset within the structure that can be changed /** Returns a list of properties, their type and offset within the structure that can be changed
by higher-level processes refering to them by name such as Lua or the property tool **/ by higher-level processes refering to them by name such as Lua or the property tool **/
static std::vector<StructProperty> GetProperties(); static std::vector<StructProperty> GetProperties();
static StructProperty GetProperty(std::string propertyName);
}; };
#endif #endif