File: Server.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • 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 (205 lines) | stat: -rw-r--r-- 4,941 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
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#pragma once
#include "Core/Lock.h"
#include "Compiler/Thread.h"
#include "Connection.h"
#include "File.h"
#include "Test.h"
#include "Repl.h"
#include "WorkQueue.h"
#include "RangeSet.h"
#include "Core/Queue.h"

namespace storm {
	namespace server {
		STORM_PKG(core.lang.server);

		// Since the preprocessor does not know ::String, we make a typedef.
		typedef ::String CString;

		/**
		 * Class encapsulating all state in the server communication.
		 */
		class Server : public ObjectOn<Compiler> {
			STORM_CLASS;
		public:
			// Create.
			STORM_CTOR Server(Connection *c);

			// Run the server loop. Blocks until the server is detached.
			void STORM_FN run();

			// Run delayed work.
			void runWork(WorkItem *item);

		private:
			// Connection.
			Connection *conn;

			// Open files.
			Map<Nat, File *> *files;

			// Keep track of some symbols we need.
			Symbol *quit;
			Symbol *supported;
			Symbol *open;
			Symbol *edit;
			Symbol *point;
			Symbol *close;
			Symbol *error;
			Symbol *indent;
			Symbol *chunkSz;
			Symbol *test;
			Symbol *debug;
			Symbol *recolor;
			Symbol *color;
			Symbol *level;
			Symbol *as;
			Symbol *t;
			Symbol *completeName;
			Symbol *documentation;
			Symbol *replAvailable;
			Symbol *replEval;
			Symbol *runSym;
			Symbol *reload;

			// Any test state required now?
			Test *testState;

			// Work queue.
			WorkQueue *work;

			// Lock taken whenever we call into a file. This is needed since thread switches can
			// occur when we call into code possibly implemented in Storm. Otherwise, background
			// tasks could interfere with message processing.
			Lock *lock;

			// Keep track of the color symbols used.
			Array<Symbol *> *colorSyms;

			/**
			 * Task posted to a Repl.
			 */
			class ReplTask {
				STORM_VALUE;
			public:
				// Create.
				STORM_CTOR ReplTask(Str *input, Package *context)
					: input(input), context(context) {}

				// Input.
				Str *input;

				// Context.
				Package *context;
			};

			/**
			 * Remember state for language REPLs.
			 */
			class RunningRepl : public ObjectOn<Compiler> {
				STORM_CLASS;
			public:
				// Create.
				STORM_CTOR RunningRepl(Server *server, Function *create);

				// Owning Server.
				Server *server;

				// Function used to create the Repl.
				Function *createFn;

				// The Repl instance. Note: This might be null if the Repl was terminated.
				Repl *repl;

				// Work items that are pending. Whenever the array is non-empty, a thread is
				// responsible for processing items for the queue.
				Queue<ReplTask> *work;

				// Main thread.
				void CODECALL run();
			};

			// Keep track of REPL instances running.
			Map<Str *, RunningRepl *> *repls;

			// Find the symbol to be used for a specific color.
			Symbol *colorSym(syntax::TokenColor color);

			// Process a message.
			Bool process(SExpr *msg);

			// Handle specific messages.
			void onSupported(SExpr *msg);
			void onOpen(SExpr *msg);
			void onEdit(SExpr *msg);
			void onPoint(SExpr *msg);
			void onClose(SExpr *msg);
			void onError(SExpr *msg);
			void onIndent(SExpr *msg);
			void onChunkSz(SExpr *msg);
			void onTest(SExpr *msg);
			void onDebug(SExpr *msg);
			void onColor(SExpr *msg);
			void onComplete(SExpr *msg);
			void onDocumentation(SExpr *msg);
			void onReplAvailable(SExpr *msg);
			void onReplEval(SExpr *msg);
			void onRun(SExpr *msg);
			void onReload(SExpr *msg);

			// Execute a function on a separate UThread.
			void CODECALL execThread(Function *fn, Bool sendResult);

			// Send updates for 'range' in 'file'.
			void update(File *file, Range range);

			// Size of the chunks to send to the client.
			static const Nat defaultChunkChars = 8000;
			Nat chunkChars;

			// Send updates for 'range' in 'file', sending one reasonabley-sized chunk now and
			// scheduling the rest for later.
			void updateLater(File *file, Range range);

			// Convenience functions for printing things.
			void print(Str *s);
			void print(const wchar *s);
			void print(const CString &s);

			// Helpers for providing documentation.
			void findDoc(Name *name, Scope scope, Array<SExpr *> *out);
			SExpr *formatDoc(Named *entity);
			SExpr *formatValue(Str *name, Named *entity, Bool ref);
			SExpr *formatValue(Str *name, Value v);
			SExpr *formatNote(const DocNote &note);
		};


		/**
		 * Schedule file updates.
		 *
		 * Stores a number of ranges to be updated so that multiple updaters do not interfere and
		 * cause too much data to be sent on each idle period.
		 */
		class UpdateFileRange : public WorkItem {
			STORM_CLASS;
		public:
			STORM_CTOR UpdateFileRange(File *file);
			STORM_CTOR UpdateFileRange(File *file, Range range);

			// Add a range.
			void STORM_FN add(Range range);

			// Merge with another item.
			Bool STORM_FN merge(WorkItem *o);

			// Execute this item.
			virtual Range STORM_FN run(WorkQueue *q);

		private:
			// Set to update.
			RangeSet *update;
		};

	}
}