1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
#include "stdafx.h"
#include "Rule.h"
#include "Node.h"
#include "Doc.h"
#include "Exception.h"
#include "Engine.h"
#include "Core/Str.h"
#include "Compiler/CodeGen.h"
#include "Compiler/Function.h"
#include "Compiler/TypeCtor.h"
namespace storm {
namespace syntax {
Rule::Rule(RuleDecl *decl, Scope scope)
: Type(decl->name, typeClass),
scope(scope),
decl(decl),
color(decl->color) {
pos = decl->pos;
setSuper(Node::stormType(engine));
if (decl->docPos.any())
documentation = new (this) SyntaxDoc(decl->docPos, this);
}
Bool Rule::loadAll() {
initTypes();
Value me = thisPtr(this);
// Transform function. This should be overloaded by all options.
Array<Value> *params = new (engine) Array<Value>();
params->push(me);
for (nat i = 0; i < tfmParams->count(); i++)
params->push(tfmParams->at(i).type());
add(lazyFunction(engine, tfmResult, S("transform"), params, fnPtr(engine, &Rule::createTransform, this)));
// Add these last.
add(new (this) TypeDefaultCtor(this));
if (!me.isActor()) {
add(new (this) TypeCopyCtor(this));
add(new (this) TypeDeepCopy(this));
}
return Type::loadAll();
}
void Rule::initTypes() {
// Already done?
if (!decl)
return;
Scope withPos = scope.withPos(pos);
tfmParams = new (this) Array<bs::ValParam>();
for (nat i = 0; i < decl->params->count(); i++) {
ParamDecl p = decl->params->at(i);
Value v = withPos.value(p.type, decl->pos);
if (v == Value())
throw new (this) SyntaxError(decl->pos, S("Rules can not take void as a parameter."));
tfmParams->push(bs::ValParam(v, p.name));
}
tfmResult = withPos.value(decl->result, decl->pos);
decl = null;
}
Array<bs::ValParam> *Rule::params() {
initTypes();
return tfmParams;
}
Value Rule::result() {
initTypes();
return tfmResult;
}
CodeGen *Rule::createTransform() {
CodeGen *code = new (this) CodeGen(runOn(), true, tfmResult);
code::Listing *l = code->l;
// Add our parameters.
code::Var me = code->createParam(thisPtr(this));
for (nat i = 0; i < tfmParams->count(); i++)
code->createParam(tfmParams->at(i).type());
*l << code::prolog();
// Call the exception-throwing function.
*l << code::fnParam(engine.ptrDesc(), me);
*l << code::fnCall(engine.ref(builtin::ruleThrow), true);
// Not needed, but for good measure.
*l << code::epilog();
*l << code::ret(Size());
return code;
}
}
}
|