mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-26 16:29:28 +00:00
Rez: Labels, $$CountOf, $$ArrayIndex
This commit is contained in:
parent
523a68d3de
commit
a02d56ba1c
@ -1,8 +1,9 @@
|
||||
#include "Expression.h"
|
||||
#include "ResourceCompiler.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
int Expression::evaluateInt(Context *ctx)
|
||||
int Expression::evaluateInt(ResourceCompiler *ctx)
|
||||
{
|
||||
throw TypeError();
|
||||
}
|
||||
@ -21,7 +22,7 @@ IntExpr::~IntExpr()
|
||||
{
|
||||
}
|
||||
|
||||
int IntExpr::evaluateInt(Context *ctx)
|
||||
int IntExpr::evaluateInt(ResourceCompiler *ctx)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
@ -41,7 +42,7 @@ BinaryExpr::~BinaryExpr()
|
||||
{
|
||||
}
|
||||
|
||||
int BinaryExpr::evaluateInt(Context *ctx)
|
||||
int BinaryExpr::evaluateInt(ResourceCompiler *ctx)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
@ -75,7 +76,7 @@ UnaryExpr::~UnaryExpr()
|
||||
{
|
||||
}
|
||||
|
||||
int UnaryExpr::evaluateInt(Context *ctx)
|
||||
int UnaryExpr::evaluateInt(ResourceCompiler *ctx)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
@ -85,3 +86,42 @@ int UnaryExpr::evaluateInt(Context *ctx)
|
||||
return ~a->evaluateInt(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IdentifierExpr::IdentifierExpr(std::string id, bool isFunction)
|
||||
: id(id), isFunction(isFunction)
|
||||
{
|
||||
}
|
||||
|
||||
void IdentifierExpr::addArgument(ExprPtr e)
|
||||
{
|
||||
arguments.push_back(e);
|
||||
}
|
||||
|
||||
int IdentifierExpr::evaluateInt(ResourceCompiler *ctx)
|
||||
{
|
||||
if(isFunction)
|
||||
{
|
||||
if(id == "$$countof" || id == "$$arrayindex")
|
||||
{
|
||||
assert(arguments.size() == 1);
|
||||
IdentifierExprPtr arr = std::dynamic_pointer_cast<IdentifierExpr>(arguments[0]);
|
||||
assert(arr);
|
||||
if(id == "$$countof")
|
||||
return ctx->getArrayCount(arr->id);
|
||||
else
|
||||
return ctx->getArrayIndex(arr->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << id << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExprPtr val = ctx->lookupIdentifier(id);
|
||||
assert(val);
|
||||
return val->evaluateInt(ctx);
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,14 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class Context
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ResourceCompiler;
|
||||
|
||||
class Expression;
|
||||
class CompoundExpr;
|
||||
class IdentifierExpr;
|
||||
typedef std::shared_ptr<Expression> ExprPtr;
|
||||
typedef std::shared_ptr<CompoundExpr> CompoundExprPtr;
|
||||
typedef std::shared_ptr<IdentifierExpr> IdentifierExprPtr;
|
||||
|
||||
|
||||
enum class BinaryOp
|
||||
@ -34,7 +31,7 @@ class TypeError
|
||||
class Expression
|
||||
{
|
||||
public:
|
||||
virtual int evaluateInt(Context *ctx);
|
||||
virtual int evaluateInt(ResourceCompiler *ctx);
|
||||
virtual ~Expression();
|
||||
};
|
||||
|
||||
@ -53,7 +50,7 @@ public:
|
||||
IntExpr(int val) : val(val) {}
|
||||
~IntExpr();
|
||||
|
||||
virtual int evaluateInt(Context *ctx);
|
||||
virtual int evaluateInt(ResourceCompiler *ctx);
|
||||
};
|
||||
|
||||
class CompoundExpr : public Expression
|
||||
@ -76,7 +73,7 @@ public:
|
||||
: op(op), a(a), b(b) {}
|
||||
~BinaryExpr();
|
||||
|
||||
virtual int evaluateInt(Context *ctx);
|
||||
virtual int evaluateInt(ResourceCompiler *ctx);
|
||||
};
|
||||
|
||||
class UnaryExpr : public Expression
|
||||
@ -88,9 +85,19 @@ public:
|
||||
: op(op), a(a) {}
|
||||
~UnaryExpr();
|
||||
|
||||
virtual int evaluateInt(Context *ctx);
|
||||
virtual int evaluateInt(ResourceCompiler *ctx);
|
||||
};
|
||||
|
||||
class IdentifierExpr : public Expression
|
||||
{
|
||||
std::string id;
|
||||
std::vector<ExprPtr> arguments;
|
||||
bool isFunction;
|
||||
public:
|
||||
IdentifierExpr(std::string id, bool isFunction = false);
|
||||
|
||||
void addArgument(ExprPtr e);
|
||||
virtual int evaluateInt(ResourceCompiler *ctx);
|
||||
};
|
||||
|
||||
#endif // EXPRESSION_H
|
||||
|
@ -1,11 +1,116 @@
|
||||
#include "ResourceCompiler.h"
|
||||
#include <iostream>
|
||||
#include "ResourceDefinitions.h"
|
||||
|
||||
ResourceCompiler::ResourceCompiler()
|
||||
ResourceCompiler::ResourceCompiler(TypeDefinitionPtr type, CompoundExprPtr body)
|
||||
: typeDefinition(type), body(body), currentOffset(0), currentField(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ResourceCompiler::write(int nBits, int value)
|
||||
{
|
||||
std::cout << "[" << nBits << " bits] = " << std::hex << value << std::dec << std::endl;
|
||||
currentOffset += nBits;
|
||||
}
|
||||
|
||||
ExprPtr ResourceCompiler::lookupIdentifier(std::string name, const Subscripts &sub)
|
||||
{
|
||||
if(currentField)
|
||||
{
|
||||
if(ExprPtr val = currentField->lookupNamedValue(name))
|
||||
return val;
|
||||
}
|
||||
|
||||
auto p = labelValues.find(std::make_pair(name, sub));
|
||||
if(p != labelValues.end())
|
||||
return p->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ResourceCompiler::defineLabel(const std::string &name)
|
||||
{
|
||||
labelValues[std::make_pair(name,currentSubscripts)] = std::make_shared<IntExpr>(currentOffset);
|
||||
}
|
||||
|
||||
void ResourceCompiler::compile()
|
||||
{
|
||||
std::cout << "(first pass)\n";
|
||||
currentOffset = 0;
|
||||
typeDefinition->compile(body, this, true);
|
||||
std::cout << "(second pass)\n";
|
||||
currentOffset = 0;
|
||||
typeDefinition->compile(body, this, false);
|
||||
std::cout << "(done)\n";
|
||||
|
||||
}
|
||||
|
||||
int ResourceCompiler::getArrayCount(const std::string &name)
|
||||
{
|
||||
Subscripts sub = currentSubscripts;
|
||||
for(;;)
|
||||
{
|
||||
auto p = arrayCounts.find(std::make_pair(name, sub));
|
||||
if(p != arrayCounts.end())
|
||||
return p->second;
|
||||
|
||||
|
||||
if(sub.empty())
|
||||
return 0; /* ### */
|
||||
sub.popSubscript();
|
||||
}
|
||||
}
|
||||
|
||||
int ResourceCompiler::getArrayIndex(const std::string &arrayName)
|
||||
{
|
||||
return curArrayIndices[arrayName];
|
||||
}
|
||||
|
||||
void ResourceCompiler::beginArrayScope(std::string &arrayName, int index)
|
||||
{
|
||||
if(arrayName != "")
|
||||
{
|
||||
curArrayIndices[arrayName] = index;
|
||||
int& count = arrayCounts[std::make_pair(arrayName, currentSubscripts)];
|
||||
if(count < index)
|
||||
count = index;
|
||||
arrayCounts[std::make_pair(arrayName, Subscripts())] = count;
|
||||
//std::cout << "count for " << arrayName << " is " << count << std::endl;
|
||||
}
|
||||
currentSubscripts.addSubscript(index);
|
||||
}
|
||||
|
||||
Subscripts::Subscripts()
|
||||
{
|
||||
}
|
||||
|
||||
Subscripts::~Subscripts()
|
||||
{
|
||||
}
|
||||
|
||||
void Subscripts::addSubscript(int x)
|
||||
{
|
||||
subscripts.push_back(x);
|
||||
}
|
||||
|
||||
void Subscripts::popSubscript()
|
||||
{
|
||||
subscripts.pop_back();
|
||||
}
|
||||
|
||||
bool Subscripts::operator<(const Subscripts &other) const
|
||||
{
|
||||
if(subscripts.size() < other.subscripts.size())
|
||||
return true;
|
||||
if(other.subscripts.size() < subscripts.size())
|
||||
return false;
|
||||
for(int i = 0, n = subscripts.size(); i < n; i++)
|
||||
{
|
||||
if(subscripts[i] < other.subscripts[i])
|
||||
return true;
|
||||
else if(subscripts[i] > other.subscripts[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -2,14 +2,69 @@
|
||||
#define RESOURCECOMPILER_H
|
||||
|
||||
#include "Expression.h"
|
||||
#include "ResourceDefinitions.h"
|
||||
|
||||
class ResourceCompiler : public Context
|
||||
class Field;
|
||||
|
||||
|
||||
class Subscripts
|
||||
{
|
||||
std::vector<int> subscripts;
|
||||
public:
|
||||
ResourceCompiler();
|
||||
Subscripts();
|
||||
~Subscripts();
|
||||
|
||||
void addSubscript(int x);
|
||||
void popSubscript();
|
||||
bool operator<(const Subscripts& other) const;
|
||||
bool empty() const { return subscripts.empty(); }
|
||||
};
|
||||
|
||||
class ResourceCompiler
|
||||
{
|
||||
TypeDefinitionPtr typeDefinition;
|
||||
CompoundExprPtr body;
|
||||
std::map<std::pair<std::string, Subscripts>, ExprPtr> labelValues;
|
||||
std::map<std::pair<std::string, Subscripts>, int> arrayCounts;
|
||||
std::map<std::string, int> curArrayIndices;
|
||||
int currentOffset;
|
||||
Field* currentField;
|
||||
Subscripts currentSubscripts;
|
||||
|
||||
void beginArrayScope(std::string& arrayName, int index);
|
||||
public:
|
||||
ResourceCompiler(TypeDefinitionPtr type, CompoundExprPtr body);
|
||||
|
||||
void reserve(int nBits) { write(nBits, 0); }
|
||||
void write(int nBits, int value);
|
||||
|
||||
ExprPtr lookupIdentifier(std::string name, const Subscripts& sub = Subscripts());
|
||||
|
||||
void defineLabel(const std::string& name);
|
||||
void compile();
|
||||
|
||||
int getArrayCount(const std::string& arrayName);
|
||||
int getArrayIndex(const std::string& arrayName);
|
||||
|
||||
class FieldScope
|
||||
{
|
||||
ResourceCompiler *compiler;
|
||||
public:
|
||||
FieldScope(ResourceCompiler* compiler, Field *field)
|
||||
: compiler(compiler) { compiler->currentField = field; }
|
||||
~FieldScope() { compiler->currentField = nullptr; }
|
||||
};
|
||||
|
||||
class ArrayScope
|
||||
{
|
||||
ResourceCompiler *compiler;
|
||||
public:
|
||||
ArrayScope(ResourceCompiler* compiler, std::string& arrayName, int index)
|
||||
: compiler(compiler) { compiler->beginArrayScope(arrayName, index); }
|
||||
~ArrayScope() { compiler->currentSubscripts.popSubscript(); }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // RESOURCECOMPILER_H
|
||||
|
@ -36,7 +36,7 @@ void FieldList::addField(FieldPtr field)
|
||||
|
||||
void FieldList::addLabel(std::string name)
|
||||
{
|
||||
// ### TODO
|
||||
addField(std::make_shared<LabelField>(name));
|
||||
}
|
||||
|
||||
void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
|
||||
@ -57,6 +57,30 @@ void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
|
||||
|
||||
|
||||
|
||||
void SimpleField::addNamedValue(std::string n)
|
||||
{
|
||||
if(lastNamedValue)
|
||||
addNamedValue(n, std::make_shared<BinaryExpr>(
|
||||
BinaryOp::PLUS, lastNamedValue, std::make_shared<IntExpr>(1)));
|
||||
else
|
||||
addNamedValue(n, std::make_shared<IntExpr>(0));
|
||||
}
|
||||
|
||||
void SimpleField::addNamedValue(std::string n, ExprPtr val)
|
||||
{
|
||||
namedValues[n] = val;
|
||||
lastNamedValue = val;
|
||||
}
|
||||
|
||||
ExprPtr SimpleField::lookupNamedValue(std::string n)
|
||||
{
|
||||
auto p = namedValues.find(n);
|
||||
if(p != namedValues.end())
|
||||
return p->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SimpleField::needsValue()
|
||||
{
|
||||
return !value;
|
||||
@ -88,6 +112,7 @@ void SimpleField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass
|
||||
int actualValue = 0;
|
||||
if(!prePass)
|
||||
{
|
||||
ResourceCompiler::FieldScope scope(compiler, this);
|
||||
if(value)
|
||||
{
|
||||
actualValue = value->evaluateInt(compiler);
|
||||
@ -121,6 +146,7 @@ void ArrayField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
|
||||
while(i < n)
|
||||
{
|
||||
++iterations;
|
||||
ResourceCompiler::ArrayScope scope(compiler, name, iterations);
|
||||
for(FieldPtr f : fields)
|
||||
{
|
||||
if(f->needsValue())
|
||||
@ -133,9 +159,25 @@ void ArrayField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
|
||||
}
|
||||
}
|
||||
|
||||
if(arrayCount)
|
||||
if(!prePass && arrayCount)
|
||||
{
|
||||
int expected = arrayCount->evaluateInt(compiler);
|
||||
assert(expected == iterations);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LabelField::LabelField(std::string name)
|
||||
: name(name)
|
||||
{
|
||||
}
|
||||
|
||||
bool LabelField::needsValue()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void LabelField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
|
||||
{
|
||||
compiler->defineLabel(name);
|
||||
}
|
||||
|
@ -57,6 +57,8 @@ public:
|
||||
virtual bool needsValue() { return true; }
|
||||
|
||||
virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) = 0;
|
||||
|
||||
virtual ExprPtr lookupNamedValue(std::string) { return nullptr; }
|
||||
};
|
||||
typedef std::shared_ptr<Field> FieldPtr;
|
||||
|
||||
@ -80,9 +82,11 @@ public:
|
||||
|
||||
ExprPtr value;
|
||||
std::map<std::string, ExprPtr> namedValues;
|
||||
ExprPtr lastNamedValue;
|
||||
|
||||
void addNamedValue(std::string n) {}
|
||||
void addNamedValue(std::string n, ExprPtr val) {}
|
||||
void addNamedValue(std::string n);
|
||||
void addNamedValue(std::string n, ExprPtr val);
|
||||
ExprPtr lookupNamedValue(std::string);
|
||||
|
||||
virtual bool needsValue();
|
||||
virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass);
|
||||
@ -95,6 +99,19 @@ inline SimpleField::Attrs operator|(SimpleField::Attrs a, SimpleField::Attrs b)
|
||||
return SimpleField::Attrs( int(a) | int(b) );
|
||||
}
|
||||
|
||||
|
||||
class LabelField : public Field
|
||||
{
|
||||
std::string name;
|
||||
public:
|
||||
LabelField(std::string name);
|
||||
|
||||
virtual bool needsValue();
|
||||
virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass);
|
||||
};
|
||||
typedef std::shared_ptr<LabelField> LabelFieldPtr;
|
||||
|
||||
|
||||
class FieldList : public Field
|
||||
{
|
||||
protected:
|
||||
|
@ -293,27 +293,33 @@ expression7 : expression8 { $$ = $1; }
|
||||
expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1); }
|
||||
| CHARLIT { $$ = std::make_shared<IntExpr>($1); }
|
||||
|
||||
| IDENTIFIER /* ### */
|
||||
| IDENTIFIER "(" function_argument_list ")"
|
||||
| IDENTIFIER "[" function_argument_list1 "]"
|
||||
| IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1); }
|
||||
| IDENTIFIER
|
||||
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1,true)); }
|
||||
"(" function_argument_list ")"
|
||||
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
|
||||
| IDENTIFIER
|
||||
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1,false)); }
|
||||
"[" function_argument_list1 "]"
|
||||
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
|
||||
| "(" expression ")" { $$ = $2; }
|
||||
|
||||
;
|
||||
|
||||
function_argument_list : %empty | function_argument_list1 ;
|
||||
function_argument_list1 : expression | function_argument_list "," expression ;
|
||||
function_argument_list1 : expression
|
||||
{ world.functionCalls.top()->addArgument($expression); }
|
||||
| function_argument_list "," expression
|
||||
{ world.functionCalls.top()->addArgument($expression); }
|
||||
;
|
||||
|
||||
resource : "resource" res_type "(" expression resource_attributes ")" "{" resource_body "}"
|
||||
{
|
||||
int id = $expression->evaluateInt(nullptr);
|
||||
std::cout << "RESOURCE " << $2 << "(" << id << ")" << std::endl;
|
||||
TypeDefinitionPtr type = world.getTypeDefinition($res_type, id);
|
||||
ResourceCompiler compiler;
|
||||
std::cout << "(first pass)\n";
|
||||
type->compile($resource_body, &compiler, true);
|
||||
std::cout << "(second pass)\n";
|
||||
type->compile($resource_body, &compiler, false);
|
||||
std::cout << "(done)\n";
|
||||
ResourceCompiler compiler(type, $resource_body);
|
||||
compiler.compile();
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -12,6 +12,7 @@ class RezWorld
|
||||
|
||||
std::map<TypeSpec, TypeDefinitionPtr> types;
|
||||
std::stack<FieldListPtr> fieldLists;
|
||||
std::stack<IdentifierExprPtr> functionCalls;
|
||||
public:
|
||||
RezWorld();
|
||||
void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type);
|
||||
|
23
Rez/Test.r
23
Rez/Test.r
@ -3,9 +3,26 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "/home/wolfgang/Projects/Retro68/CExamples/Sample.r"
|
||||
//#include "/home/wolfgang/Projects/Retro68/CExamples/Sample.r"
|
||||
|
||||
type 'TEST' {
|
||||
boolean itemUnlocked = false, // defined attributes bits...
|
||||
itemLocked = true;
|
||||
integer zero, one, two, answer = 42, missed;
|
||||
longint;
|
||||
//integer = (after - before) / 32;
|
||||
integer = $$CountOf(foo);
|
||||
before:
|
||||
array foo {
|
||||
integer = $$ArrayIndex(foo);
|
||||
integer;
|
||||
integer;
|
||||
};
|
||||
after:
|
||||
;
|
||||
};
|
||||
|
||||
resource 'TEST' (128) {
|
||||
answer,
|
||||
0x1234,
|
||||
{ 1, 2; 3, 4; }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user