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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,10 @@
//Syntax analyser
#include "Parser.h"
#include "Format.h"
#include "Types.h"
#include "Exceptions.h"
#include "simulation/Particle.h"
#include "simulation/StructProperty.h"
namespace pim
{
namespace compiler
@ -106,7 +110,18 @@ namespace pim
*/
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::DecimalSymbol))
if(!accept(Token::ParticleSymbol))
@ -130,7 +145,18 @@ namespace pim
*/
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::DecimalSymbol))
if(!accept(Token::ParticleSymbol))
@ -296,7 +322,7 @@ namespace pim
generator->PushLocalScope(loopLabel+"Start");
neighbourVariable = token.Source;
expect(Token::Identifier);
generator->ScopeVariableType(Token::IntegerConstant);
generator->ScopeVariableType(DataType::Integer);
generator->ScopeVariable(neighbourVariable);
generator->ScopeVariable(xVar);
generator->ScopeVariable(yVar);
@ -471,6 +497,22 @@ namespace pim
expect(Token::Identifier);
expect(Token::AssignSymbol);
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->StoreProperty(property);
}

View File

@ -10,22 +10,6 @@ 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 Parser
{
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();
unsigned char * esi = new unsigned char[1024*1024];//malloc(1024*1024);
esi += 512;
//int * esi = malloc(1024*1024);
emit("BE"); //mov esi, machineStack
emit((intptr_t)esi);
while(programCounter < romSize)
{
Word argument = rom[programCounter].Parameter;
@ -215,6 +216,14 @@ namespace pim
emit("83 C6 08"); //add esi, 8
}
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:
emit("83 C6 08"); //add esi, 8
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)));
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
by higher-level processes refering to them by name such as Lua or the property tool **/
static std::vector<StructProperty> GetProperties();
static StructProperty GetProperty(std::string propertyName);
};
#endif