From a02d56ba1c92bea977cf3fb85295ee85b5678536 Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Wed, 8 Oct 2014 00:41:40 +0200 Subject: [PATCH] Rez: Labels, $$CountOf, $$ArrayIndex --- Rez/Expression.cc | 52 +++++++++++++++--- Rez/Expression.h | 27 ++++++---- Rez/ResourceCompiler.cc | 107 ++++++++++++++++++++++++++++++++++++- Rez/ResourceCompiler.h | 59 +++++++++++++++++++- Rez/ResourceDefinitions.cc | 46 +++++++++++++++- Rez/ResourceDefinitions.h | 21 +++++++- Rez/RezParser.yy | 26 +++++---- Rez/RezWorld.h | 1 + Rez/Test.r | 23 ++++++-- 9 files changed, 326 insertions(+), 36 deletions(-) diff --git a/Rez/Expression.cc b/Rez/Expression.cc index dfa3208764..0f5ff22ee5 100644 --- a/Rez/Expression.cc +++ b/Rez/Expression.cc @@ -1,8 +1,9 @@ #include "Expression.h" +#include "ResourceCompiler.h" +#include +#include - - -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(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); + } +} diff --git a/Rez/Expression.h b/Rez/Expression.h index ec10db222e..697f694592 100644 --- a/Rez/Expression.h +++ b/Rez/Expression.h @@ -4,17 +4,14 @@ #include #include -class Context -{ - -}; - - +class ResourceCompiler; class Expression; class CompoundExpr; +class IdentifierExpr; typedef std::shared_ptr ExprPtr; typedef std::shared_ptr CompoundExprPtr; +typedef std::shared_ptr 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 arguments; + bool isFunction; +public: + IdentifierExpr(std::string id, bool isFunction = false); + void addArgument(ExprPtr e); + virtual int evaluateInt(ResourceCompiler *ctx); +}; #endif // EXPRESSION_H diff --git a/Rez/ResourceCompiler.cc b/Rez/ResourceCompiler.cc index 533624448f..d54798d05e 100644 --- a/Rez/ResourceCompiler.cc +++ b/Rez/ResourceCompiler.cc @@ -1,11 +1,116 @@ #include "ResourceCompiler.h" #include +#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(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; } diff --git a/Rez/ResourceCompiler.h b/Rez/ResourceCompiler.h index 4523557183..95f3f60cbf 100644 --- a/Rez/ResourceCompiler.h +++ b/Rez/ResourceCompiler.h @@ -2,14 +2,69 @@ #define RESOURCECOMPILER_H #include "Expression.h" +#include "ResourceDefinitions.h" -class ResourceCompiler : public Context +class Field; + + +class Subscripts { + std::vector 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, ExprPtr> labelValues; + std::map, int> arrayCounts; + std::map 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 diff --git a/Rez/ResourceDefinitions.cc b/Rez/ResourceDefinitions.cc index 3af85e9524..3cdc84f48d 100644 --- a/Rez/ResourceDefinitions.cc +++ b/Rez/ResourceDefinitions.cc @@ -36,7 +36,7 @@ void FieldList::addField(FieldPtr field) void FieldList::addLabel(std::string name) { - // ### TODO + addField(std::make_shared(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( + BinaryOp::PLUS, lastNamedValue, std::make_shared(1))); + else + addNamedValue(n, std::make_shared(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); +} diff --git a/Rez/ResourceDefinitions.h b/Rez/ResourceDefinitions.h index 085c1cf629..093346db40 100644 --- a/Rez/ResourceDefinitions.h +++ b/Rez/ResourceDefinitions.h @@ -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 FieldPtr; @@ -80,9 +82,11 @@ public: ExprPtr value; std::map 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 LabelFieldPtr; + + class FieldList : public Field { protected: diff --git a/Rez/RezParser.yy b/Rez/RezParser.yy index 8875ad5da5..e566f4efef 100644 --- a/Rez/RezParser.yy +++ b/Rez/RezParser.yy @@ -293,27 +293,33 @@ expression7 : expression8 { $$ = $1; } expression8 : INTLIT { $$ = std::make_shared($1); } | CHARLIT { $$ = std::make_shared($1); } - | IDENTIFIER /* ### */ - | IDENTIFIER "(" function_argument_list ")" - | IDENTIFIER "[" function_argument_list1 "]" + | IDENTIFIER { $$ = std::make_shared($1); } + | IDENTIFIER + { world.functionCalls.push(std::make_shared($1,true)); } + "(" function_argument_list ")" + { $$ = world.functionCalls.top(); world.functionCalls.pop(); } + | IDENTIFIER + { world.functionCalls.push(std::make_shared($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(); } ; diff --git a/Rez/RezWorld.h b/Rez/RezWorld.h index 63f205bcfb..ae42589fc8 100644 --- a/Rez/RezWorld.h +++ b/Rez/RezWorld.h @@ -12,6 +12,7 @@ class RezWorld std::map types; std::stack fieldLists; + std::stack functionCalls; public: RezWorld(); void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type); diff --git a/Rez/Test.r b/Rez/Test.r index 173917529b..6679348422 100644 --- a/Rez/Test.r +++ b/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; } +}; +