File: Rule.cpp

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (107 lines) | stat: -rw-r--r-- 2,491 bytes parent folder | download | duplicates (2)
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;
		}

	}
}