This file is indexed.

/usr/include/aseba/compiler/compiler.h is in aseba 1.6.0-3.1~build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
/*
	Aseba - an event-based framework for distributed robot control
	Copyright (C) 2007--2016:
		Stephane Magnenat <stephane at magnenat dot net>
		(http://stephane.magnenat.net)
		and other contributors, see authors.txt for details
	
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published
	by the Free Software Foundation, version 3 of the License.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.
	
	You should have received a copy of the GNU Lesser General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __ASEBA_COMPILER_H
#define __ASEBA_COMPILER_H

#include <utility>
#include <vector>
#include <deque>
#include <string>
#include <map>
#include <set>
#include <utility>
#include <istream>

#include "errors_code.h"
#include "../common/types.h"
#include "../common/msg/TargetDescription.h"
#include "../common/utils/FormatableString.h"

namespace Aseba
{
	/**
		\defgroup compiler AESL Compiler
	*/
	/*@{*/

	// pre-declaration
	struct Node;
	struct ProgramNode;
	struct StatementNode;
	struct BinaryArithmeticNode;
	struct AssignmentNode;
	struct TupleVectorNode;
	struct MemoryVectorNode;
	
	//! A bytecode element 
	struct BytecodeElement
	{
		BytecodeElement() = default;
		BytecodeElement(unsigned short bytecode) : bytecode(bytecode), line(0) { }
		BytecodeElement(unsigned short bytecode, unsigned short line) : bytecode(bytecode), line(line) { }
		operator unsigned short () const { return bytecode; }
		unsigned getWordSize() const;
		
		unsigned short bytecode{0xffff}; //! bytecode itself
		unsigned short line{0}; //!< line in source code
	};
	
	//! Bytecode array in the form of a dequeue, for construction
	struct BytecodeVector: std::deque<BytecodeElement>
	{
		//! Constructor
		BytecodeVector() = default;
		
		unsigned maxStackDepth{0}; //!< maximum depth of the stack used by all the computations of the bytecode
		unsigned callDepth{0}; //!< for callable bytecode (i.e. subroutines), used in analysis of stack check
		unsigned lastLine{0}; //!< last line added, normally equal *this[this->size()-1].line, but may differ for instance on loops
		
		void push_back(const BytecodeElement& be)
		{
			std::deque<BytecodeElement>::push_back(be);
			lastLine = be.line;
		}
		
		void changeStopToRetSub();
		unsigned short getTypeOfLast() const;
		
		//! A map of event addresses to identifiers
		typedef std::map<unsigned, unsigned> EventAddressesToIdsMap;
		EventAddressesToIdsMap getEventAddressesToIds() const;
	};
	
	// predeclaration
	struct PreLinkBytecode;
	
	//! Position in a source file or string. First is line, second is column
	struct SourcePos
	{
		unsigned character{0}; //!< position in source text
		unsigned row{0}; //!< line in source text
		unsigned column{0}; //!< column in source text
		bool valid{false}; //!< true if character, row and column hold valid values
		
		SourcePos(unsigned character, unsigned row, unsigned column) : character(character - 1), row(row), column(column - 1) { valid = true; }
		SourcePos() = default;
		std::wstring toWString() const;
	};
	
	//! Return error messages based on error ID (needed to translate messages for other applications)
	struct ErrorMessages
	{
		ErrorMessages();

		//! Type of the callback
		using ErrorCallback = const std::wstring (*)(ErrorCode);
		//! Default callback
		static const std::wstring defaultCallback(ErrorCode error);
	};

	//! Compilation error
	struct Error
	{
		SourcePos pos; //!< position of error in source string
		std::wstring message = L"not defined"; //!< message
		//! Create an error at pos
		Error(const SourcePos& pos, std::wstring  message) : pos(pos), message(std::move(message)) { }
		//! Create an empty error
		Error() = default;

		//! Return a string describing the error
		std::wstring toWString() const;
	};

	struct TranslatableError : public Error
	{
		TranslatableError() : Error() {}
		TranslatableError(const SourcePos& pos, ErrorCode error);
		TranslatableError &arg(int value, int fieldWidth = 0, int base = 10, wchar_t fillChar = ' ');
		TranslatableError &arg(long int value, int fieldWidth = 0, int base = 10, wchar_t fillChar = ' ');
		TranslatableError &arg(unsigned value, int fieldWidth = 0, int base = 10, wchar_t fillChar = ' ');
		TranslatableError &arg(float value, int fieldWidth = 0, int precision = 6, wchar_t fillChar = ' ');
		TranslatableError &arg(const std::wstring& value);

		Error toError();
		static void setTranslateCB(ErrorMessages::ErrorCallback newCB);

		static ErrorMessages::ErrorCallback translateCB;
		WFormatableString message;
	};

	//! Vector of names of variables
	using VariablesNamesVector = std::vector<std::wstring>;
	
	//! A name - value pair
	struct NamedValue
	{
		//! Create a filled pair
		NamedValue(std::wstring  name, int value) : name(std::move(name)), value(value) {}
		
		std::wstring name; //!< name part of the pair
		int value; //!< value part of the pair
	};
	
	//! An event description is a name - value pair
	using EventDescription = NamedValue;
	
	//! An constant definition is a name - value pair
	using ConstantDefinition = NamedValue;
	
	//! Generic vector of name - value pairs
	struct NamedValuesVector: public std::vector<NamedValue>
	{
		bool contains(const std::wstring& s, size_t* position = nullptr) const;
	};
	
	//! Vector of events descriptions
	using EventsDescriptionsVector = NamedValuesVector;
	
	//! Vector of constants definitions
	using ConstantsDefinitions = NamedValuesVector;
	
	//! Definitions common to several nodes, such as events or some constants
	struct CommonDefinitions
	{
		//! All defined events
		EventsDescriptionsVector events;
		//! All globally defined constants
		ConstantsDefinitions constants;
		
		//! Clear all the content
		void clear() { events.clear(); constants.clear(); }
	};
	
	//! Aseba Event Scripting Language compiler
	class Compiler
	{
	public:
		//! A token is a parsed element of inputs
		struct Token
		{
			enum Type
			{
				TOKEN_END_OF_STREAM = 0,
				TOKEN_STR_when,
				TOKEN_STR_emit,
				TOKEN_STR_hidden_emit,
				TOKEN_STR_for,
				TOKEN_STR_in,
				TOKEN_STR_step,
				TOKEN_STR_while,
				TOKEN_STR_do,
				TOKEN_STR_if,
				TOKEN_STR_then,
				TOKEN_STR_else,
				TOKEN_STR_elseif,
				TOKEN_STR_end,
				TOKEN_STR_var,
				TOKEN_STR_const,
				TOKEN_STR_call,
				TOKEN_STR_sub,
				TOKEN_STR_callsub,
				TOKEN_STR_onevent,
				TOKEN_STR_abs,
				TOKEN_STR_return,
				TOKEN_STRING_LITERAL,
				TOKEN_INT_LITERAL,
				TOKEN_PAR_OPEN,
				TOKEN_PAR_CLOSE,
				TOKEN_BRACKET_OPEN,
				TOKEN_BRACKET_CLOSE,
				TOKEN_COLON,
				TOKEN_COMMA,
				TOKEN_ASSIGN,
				TOKEN_OP_OR,
				TOKEN_OP_AND,
				TOKEN_OP_NOT,

				TOKEN_OP_EQUAL,			// group of tokens, don't split or mess up
				TOKEN_OP_NOT_EQUAL,		//
				TOKEN_OP_BIGGER,		//
				TOKEN_OP_BIGGER_EQUAL,		//
				TOKEN_OP_SMALLER,		//
				TOKEN_OP_SMALLER_EQUAL,		//

				TOKEN_OP_ADD,			// group of 2 tokens, don't split or mess up
				TOKEN_OP_NEG,			//
				TOKEN_OP_MULT,			// group of 3 tokens, don't split or mess up
				TOKEN_OP_DIV,			//
				TOKEN_OP_MOD,			//
				TOKEN_OP_SHIFT_LEFT,		// group of 2 tokens, don't split or mess up
				TOKEN_OP_SHIFT_RIGHT,		//
				TOKEN_OP_BIT_OR,		// group of 4 tokens, don't split or mess up
				TOKEN_OP_BIT_XOR,		//
				TOKEN_OP_BIT_AND,		//
				TOKEN_OP_BIT_NOT,		//

				TOKEN_OP_ADD_EQUAL,		// group of 12 tokens, don't split or mess up
				TOKEN_OP_NEG_EQUAL,		//
				TOKEN_OP_MULT_EQUAL,		//
				TOKEN_OP_DIV_EQUAL,		//
				TOKEN_OP_MOD_EQUAL,		//
				TOKEN_OP_SHIFT_LEFT_EQUAL,	//
				TOKEN_OP_SHIFT_RIGHT_EQUAL,	//
				TOKEN_OP_BIT_OR_EQUAL,		//
				TOKEN_OP_BIT_XOR_EQUAL,		//
				TOKEN_OP_BIT_AND_EQUAL,		//

				TOKEN_OP_PLUS_PLUS,
				TOKEN_OP_MINUS_MINUS

			} type{TOKEN_END_OF_STREAM}; //!< type of this token
			std::wstring sValue; //!< string version of the value
			int iValue{0}; //!< int version of the value, 0 if not applicable
			SourcePos pos;//!< position of token in source code
			
			Token()  = default;
			Token(Type type, SourcePos pos = SourcePos(), const std::wstring& value = L"");
			const std::wstring typeName() const;
			std::wstring toWString() const;
			operator Type () const { return type; }
		};
		
		//! Description of a subroutine
		struct SubroutineDescriptor
		{
			std::wstring name;
			unsigned address;
			unsigned line;
			
			SubroutineDescriptor(std::wstring  name, unsigned address, unsigned line) : name(std::move(name)), address(address), line(line) {}
		};
		//! Lookup table for subroutines id => (name, address, line)
		using SubroutineTable = std::vector<SubroutineDescriptor>;
		//! Reverse Lookup table for subroutines name => id
		typedef std::map<std::wstring, unsigned> SubroutineReverseTable;
		//! Lookup table to keep track of implemented events
		using ImplementedEvents = std::set<unsigned int>;
		//! Lookup table for constant name => value
		typedef std::map<std::wstring, int> ConstantsMap;
		//! Lookup table for event name => id
		typedef std::map<std::wstring, unsigned> EventsMap;

		friend struct AssignmentNode;
		friend struct CallSubNode;
	
	public:
		Compiler();
		void setTargetDescription(const TargetDescription *description);
		const TargetDescription *getTargetDescription() const { return targetDescription;}
		const VariablesMap *getVariablesMap() const { return &variablesMap; }
		const SubroutineTable *getSubroutineTable() const { return &subroutineTable; }
		void setCommonDefinitions(const CommonDefinitions *definitions);
		bool compile(std::wistream& source, BytecodeVector& bytecode, unsigned& allocatedVariablesCount, Error &errorDescription, std::wostream* dump = nullptr);
		void setTranslateCallback(ErrorMessages::ErrorCallback newCB) { TranslatableError::setTranslateCB(newCB); }
		static std::wstring translate(ErrorCode error) { return TranslatableError::translateCB(error); }
		static bool isKeyword(const std::wstring& word);
		
	protected:
		void internalCompilerError() const;
		void expect(const Token::Type& type) const;
		unsigned expectUInt12Literal() const;
		unsigned expectUInt16Literal() const;
		unsigned expectPositiveInt16Literal() const;
		int expectAbsoluteInt16Literal(bool negative) const;
		unsigned expectPositiveConstant() const;
		int expectConstant() const;
		unsigned expectPositiveInt16LiteralOrConstant() const;
		int expectInt16Literal();
		int expectInt16LiteralOrConstant();
		unsigned expectGlobalEventId() const;
		unsigned expectAnyEventId() const;
		std::wstring eventName(unsigned eventId) const;
		template <int length>
		bool isOneOf(const Token::Type types[length]) const;
		template <int length>
		void expectOneOf(const Token::Type types[length]) const;

		void freeTemporaryMemory();
		unsigned allocateTemporaryMemory(const SourcePos varPos, const unsigned size);
		AssignmentNode* allocateTemporaryVariable(const SourcePos varPos, Node* rValue);

		VariablesMap::const_iterator findVariable(const std::wstring& name, const SourcePos& pos) const;
		FunctionsMap::const_iterator findFunction(const std::wstring& name, const SourcePos& pos) const;
		ConstantsMap::const_iterator findConstant(const std::wstring& name, const SourcePos& pos) const;
		EventsMap::const_iterator findGlobalEvent(const std::wstring& name, const SourcePos& pos) const;
		EventsMap::const_iterator findAnyEvent(const std::wstring& name, const SourcePos& pos) const;
		SubroutineReverseTable::const_iterator findSubroutine(const std::wstring& name, const SourcePos& pos) const;
		bool constantExists(const std::wstring& name) const;
		void buildMaps();
		void tokenize(std::wistream& source);
		wchar_t getNextCharacter(std::wistream& source, SourcePos& pos);
		bool testNextCharacter(std::wistream& source, SourcePos& pos, wchar_t test, Token::Type tokenIfTrue);
		void dumpTokens(std::wostream &dest) const;
		bool verifyStackCalls(PreLinkBytecode& preLinkBytecode);
		bool link(const PreLinkBytecode& preLinkBytecode, BytecodeVector& bytecode);
		void disassemble(BytecodeVector& bytecode, const PreLinkBytecode& preLinkBytecode, std::wostream& dump) const;
		
	protected:
		Node* parseProgram();
		
		Node* parseStatement();
		
		Node* parseBlockStatement();
		
		Node* parseReturn();
		void parseConstDef();
		Node* parseVarDef();
		AssignmentNode* parseVarDefInit(MemoryVectorNode* lValue);
		Node* parseAssignment();
		Node* parseIfWhen(bool edgeSensitive);
		Node* parseFor();
		Node* parseWhile();
		Node* parseOnEvent();
		Node* parseEmit(bool shorterArgsAllowed = false);
		Node* parseSubDecl();
		Node* parseCallSub();
		
		Node* parseOr();
		Node* parseAnd();
		Node* parseNot();
		
		Node* parseCondition();
		
		Node *parseBinaryOrExpression();
		Node *parseBinaryXorExpression();
		Node *parseBinaryAndExpression();
		
		Node* parseShiftExpression();
		Node* parseAddExpression();
		Node* parseMultExpression();
		Node* parseUnaryExpression();
		Node* parseFunctionCall();

		TupleVectorNode* parseTupleVector(bool compatibility = false);
		Node* parseConstantAndVariable();
		MemoryVectorNode* parseVariable();
		unsigned parseVariableDefSize();
		Node* tryParsingConstantExpression(SourcePos pos, int& constantResult);
		int expectConstantExpression(SourcePos pos, Node* tree);
	
	protected:
		std::deque<Token> tokens; //!< parsed tokens
		VariablesMap variablesMap; //!< variables lookup
		ImplementedEvents implementedEvents; //!< list of implemented events
		FunctionsMap functionsMap; //!< functions lookup
		ConstantsMap constantsMap; //!< constants map
		EventsMap globalEventsMap; //!< global-events map
		EventsMap allEventsMap; //!< all-events map
		SubroutineTable subroutineTable; //!< subroutine lookup
		SubroutineReverseTable subroutineReverseTable; //!< subroutine reverse lookup
		unsigned freeVariableIndex; //!< index pointing to the first free variable
		unsigned endVariableIndex; //!< (endMemory - endVariableIndex) is pointing to the first free variable at the end
		const TargetDescription *targetDescription; //!< description of the target VM
		const CommonDefinitions *commonDefinitions; //!< common definitions, such as events or some constants

		ErrorMessages translator;
	}; // Compiler
	
	//! Bytecode use for compilation previous to linking
	struct PreLinkBytecode
	{
		//! Map of events id to event bytecode
		typedef std::map<unsigned, BytecodeVector> EventsBytecode;
		EventsBytecode events; //!< bytecode for events
		
		//! Map of routines id to routine bytecode
		typedef std::map<unsigned, BytecodeVector> SubroutinesBytecode;
		SubroutinesBytecode subroutines; //!< bytecode for routines
		
		BytecodeVector *current; //!< pointer to bytecode being constructed
		
		PreLinkBytecode();
		
		void fixup(const Compiler::SubroutineTable &subroutineTable);
	};
	
	/*@}*/
	
} // namespace Aseba

#endif