File: Lookup.cpp

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; 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 (135 lines) | stat: -rw-r--r-- 3,700 bytes parent folder | download
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "stdafx.h"
#include "Lookup.h"
#include "Package.h"
#include "Engine.h"
#include "Compiler/Syntax/Reader.h"

namespace storm {
	namespace bs {

		BSLookup::BSLookup() : ScopeLookup(S("void")) {
			toInclude = new (this) Array<Package *>();
			inIncludes = new (this) Set<TObject *>();
		}

		BSLookup::BSLookup(Array<Package *> *inc) : ScopeLookup(S("void")) {
			toInclude = new (this) Array<Package *>();
			inIncludes = new (this) Set<TObject *>();
			for (Nat i = 0; i < inc->count(); i++)
				addInclude(inc->at(i), true);
		}

		ScopeLookup *BSLookup::clone() const {
			BSLookup *copy = new (this) BSLookup();
			copy->toInclude->append(toInclude);
			copy->inIncludes = new (this) Set<TObject *>(*inIncludes);
			return copy;
		}

		Bool BSLookup::addInclude(Package *p) {
			return addInclude(p, true);
		}

		Bool BSLookup::addInclude(Package *p, Bool useExports) {
			if (inIncludes->has(p))
				return false;

			inIncludes->put(p);
			toInclude->push(p);

			if (useExports) {
				Array<Package *> *add = p->exports();
				for (Nat i = 0; i < add->count(); i++)
					addInclude(add->at(i), true);
			}

			return true;
		}

		Array<Package *> *BSLookup::includes() const {
			return new (this) Array<Package *>(*toInclude);
		}

		static Named *findFirstParam(Scope s, SimpleName *name, Bool scope) {
			if (name->count() != 1)
				return null;

			for (SimplePart *last = name->last(); last; last = last->nextOption()) {
				if (!last->params->any() || last->scopeParam(0) != scope)
					continue;

				Value firstParam = last->params->at(0);
				if (!firstParam.type)
					continue;

				if (Named *r = firstParam.type->find(last, s))
					return r;

				// TODO: Also look in the parent scope of the last type? This will fix issues
				// with 2 / 0.2 etc.
			}

			return null;
		}

		Named *BSLookup::find(Scope s, SimpleName *name) {
			// 1: If the first parameter is marked as scope-altering, prioritize lookups there.
			if (Named *found = findFirstParam(s, name, true))
				return found;

			// 2: Traverse until we reach the root.
			for (NameLookup *at = s.top; at; at = ScopeLookup::nextCandidate(at)) {
				if (Named *found = storm::find(s, at, name))
					return found;
			}

			// 3: Now we are at a location where we can start looking for more "complex" things. At
			// this point, we try to examine the first parameters if the name only contains of a
			// single part. This is since users expect x.foo() to examine the scope of 'x', and
			// since this is equivalent to foo(x).
			if (Named *found = findFirstParam(s, name, false))
				return found;

			// 4: Look in the root package.
			if (Named *found = storm::find(s, engine().corePackage(), name))
				return found;

			// 5: Lastly, examine imported packages.
			for (Nat i = 0; i < toInclude->count(); i++) {
				if (Named *found = storm::find(s, toInclude->at(i), name))
					return found;
			}

			return null;
		}

		void BSLookup::addSyntax(Scope from, syntax::ParserBase *to) {
			// Note: We have already considered exports, so we ask the syntax pkg to not look at exports either.

			// Current package.
			to->addSyntax(firstPkg(from.top), false);

			for (Nat i = 0; i < toInclude->count(); i++)
				to->addSyntax(toInclude->at(i), false);
		}

		Bool addInclude(Scope to, Package *pkg) {
			if (BSLookup *s = as<BSLookup>(to.lookup)) {
				s->addInclude(pkg);
				return true;
			} else {
				WARNING(L"This is not what you want to do!");
				return false;
			}
		}

		void addSyntax(Scope scope, syntax::ParserBase *to) {
			if (BSLookup *s = as<BSLookup>(scope.lookup)) {
				s->addSyntax(scope, to);
			} else {
				WARNING(L"This is probably not what you want to do!");
			}
		}

	}
}