tointeger and tofloat instructions. Detection and implicit conversion of number types

This commit is contained in:
Simon Robertshaw 2013-02-01 15:21:21 +00:00
parent 833cbf9b77
commit 187bf11d3d
10 changed files with 131 additions and 63 deletions

View File

@ -958,8 +958,8 @@ int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS)
machine->CSPush(i); machine->CSPush(i);
machine->CSPush(x); machine->CSPush(x);
machine->CSPush(y); machine->CSPush(y);
machine->Call(0); //machine->Call(0);
//machine->CallCompiled(0); machine->CallCompiled(0);
/*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type]; /*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type];

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;
@ -331,12 +337,34 @@ namespace pim
} }
} }
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));
currentScope->FrameSize += 4; currentScope->FrameSize += 4;
currentScope->LocalFrameSize += 4; currentScope->LocalFrameSize += 4;
typeStack.pop();
output << "#declare " << label << " " << currentScope->LocalFrameSize-4 << std::endl; output << "#declare " << label << " " << currentScope->LocalFrameSize-4 << std::endl;
} }
@ -361,20 +389,8 @@ namespace pim
void Generator::StoreVariable(std::string label) void Generator::StoreVariable(std::string label)
{ {
Definition d = currentScope->GetDefinition(label); Definition d = currentScope->GetDefinition(label);
int otherType = typeStack.top(); AssureType(d.Type);
popType(1);
if(otherType != d.Type)
{
if(otherType == DataType::Integer && d.Type == DataType::Float)
{
ToFloat();
}
else if(otherType == DataType::Float && d.Type == DataType::Integer)
{
ToInteger();
}
}
popType(2);
writeOpcode(Opcode::Store); writeOpcode(Opcode::Store);
@ -461,6 +477,8 @@ namespace pim
popType(1); popType(1);
pushType(DataType::Integer); pushType(DataType::Integer);
writeOpcode(Opcode::ToInteger); writeOpcode(Opcode::ToInteger);
output << "ftoi" << std::endl;
} }
void Generator::ToFloat() void Generator::ToFloat()
@ -468,6 +486,8 @@ namespace pim
popType(1); popType(1);
pushType(DataType::Float); pushType(DataType::Float);
writeOpcode(Opcode::ToFloat); writeOpcode(Opcode::ToFloat);
output << "itof" << std::endl;
} }
void Generator::Divide() void Generator::Divide()
@ -481,9 +501,9 @@ namespace pim
void Generator::Modulus() void Generator::Modulus()
{ {
writeOpcode(Opcode::Modulus);
popType(2); popType(2);
pushType(DataType::Integer); pushType(DataType::Integer);
writeOpcode(Opcode::Modulus);
output << "add" << std::endl; output << "add" << std::endl;
} }
@ -538,7 +558,7 @@ namespace pim
void Generator::LoadProperty(std::string property) void Generator::LoadProperty(std::string property)
{ {
popType(2); popType(1);
pushType(DataType::Integer); pushType(DataType::Integer);
writeOpcode(Opcode::LoadProperty); writeOpcode(Opcode::LoadProperty);
writeConstantPropertyPlaceholder(property); writeConstantPropertyPlaceholder(property);
@ -548,24 +568,16 @@ namespace pim
void Generator::StoreProperty(std::string property) void Generator::StoreProperty(std::string property)
{ {
popType(2); 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); popType(2);

View File

@ -131,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();
@ -174,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

@ -270,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,9 @@
#include "Parser.h" #include "Parser.h"
#include "Format.h" #include "Format.h"
#include "Types.h" #include "Types.h"
#include "Exceptions.h"
#include "simulation/Particle.h"
#include "simulation/StructProperty.h"
namespace pim namespace pim
{ {
namespace compiler namespace compiler
@ -494,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;

View File

@ -11,15 +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);
//emit("81 EC"); //sub esp, 12
//emit(12);
#ifdef DEBUG
emit("81 C4"); //add esp, 4
emit(4);
#endif
while(programCounter < romSize) while(programCounter < romSize)
{ {
Word argument = rom[programCounter].Parameter; Word argument = rom[programCounter].Parameter;
@ -221,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]
@ -290,12 +293,6 @@ namespace pim
//std::cout << programStack << std::endl; //std::cout << programStack << std::endl;
programCounter++; programCounter++;
} }
#ifdef DEBUG
emit("81 EC"); //sub esp, 4
//emit("81 EC"); //sub esp, 4
emit(4);
emit("C9"); //leave //When -fomit-frame-pointers is used, don't 'leave', since ebp isn't on the stack
#endif
for(std::map<int, int>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter) for(std::map<int, int>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter)
{ {
std::pair<int, int> placeholder = *iter; std::pair<int, int> placeholder = *iter;

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