Project

General

Profile

Транслятор с языка Sim-nML » History » Version 2

Alexander Kamkin, 09/30/2011 02:14 PM

1 1 Alexander Kamkin
h1. Транслятор с языка Sim-nML
2
3
Данный документ содержит описание схемы трансляции спецификаций микропроцессоров на языке Sim-nML в набор Java классов, которые могут быть использованы инструментом MicroTESK для автоматизированной генерации тестовых программ.
4
5
h2. Язык Sim-nML
6
7
Язык Sim-nML является расширением языка nML.
8
9
h2. Java классы, создаваемые при трансляции
10
11
Список Java классов, которые создаются при трансляции:
12 2 Alexander Kamkin
13
#Класс @ProcessorName@, который наследуется от класса @Processor@. Содержит большую часть информации о специфицируемом процессоре.
14
15
>> *TODO:* уточнить, каким образом формируется имя этого класса. Возможен вариант получаеть это имя из имени файла со спецификацией на Sim-nML, или же можно требовать задавания этого имени от пользователя в качестве одного из параметров метода, который осуществляет трансляцию, или же можно использовать какие-то специальные аннотации в самой спецификации.
16
17 1 Alexander Kamkin
Правила грамматики для «общих» нетерминальных символов
18
Бинарная операция
19
Правила грамматики для определения бинарных операций.
20
BinOp
21
:
22
''+''
23
24
|
25
''-''
26
27
|
28
''*''
29
30
|
31
''/''
32
33
|
34
''%''
35
36
|
37
DOUBLE_STAR
38
39
|
40
LEFT_SHIFT
41
42
|
43
RIGHT_SHIFT
44
45
|
46
ROTATE_LEFT
47
48
|
49
ROTATE_LEFT
50
51
|
52
ROTATE_RIGHT
53
54
|
55
''<''
56
57
|
58
''>''
59
60
|
61
LEQ
62
63
|
64
GEQ
65
66
|
67
EQ
68
69
|
70
NEQ
71
72
|
73
''&''
74
75
|
76
''^''
77
78
|
79
''|''
80
81
|
82
AND
83
84
|
85
OR
86
Числовая константа
87
Правила грамматики для определения числовых констант.
88
ConstNumExpr
89
:
90
ConstExprVal
91
92
|
93
ConstNumExpr BinOp ConstExprVal
94
ConstExprVal
95
:
96
CARD_CONST
97
98
|
99
FIXED_CONST
100
101
|
102
HEX_CONST
103
104
|
105
''!'' ConstNumExpr
106
107
|
108
''~'' ConstNumExpr
109
110
|
111
''+'' ConstNumExpr %prec ''~''
112
113
|
114
''-'' ConstNumExpr %prec ''~''
115
116
|
117
''('' ConstNumExpr '')''
118
TODO: предлагается все числовые константные выражения сразу вычислять, в оттранслированный Java код вставлять уже только значения выражений.
119
Выражение
120
Правила грамматики для определения выражений
121
Bit_Expr
122
:
123
ID
124
125
|
126
Bit_Expr ''+'' Bit_Expr
127
128
|
129
Bit_Expr ''-'' Bit_Expr
130
131
|
132
Bit_Expr ''*'' Bit_Expr
133
134
|
135
Bit_Expr ''/'' Bit_Expr
136
137
|
138
Bit_Expr ''%'' Bit_Expr
139
140
|
141
Bit_Expr DOUBLE_STAR Bit_Expr
142
143
|
144
''('' Bit_Expr '')''
145
146
|
147
FIXED_CONST
148
149
|
150
CARD_CONST
151
152
|
153
STRING_CONST
154
155
|
156
BINARY_CONST
157
158
|
159
HEX_CONST
160
OR правило
161
OrRule
162
:
163
Identifier_Or_List
164
Identifier_Or_List
165
:
166
ID
167
168
|
169
Identifier_Or_List ''|'' ID
170
AND правило
171
AndRule
172
:
173
''('' ParamList '')''
174
ParamList
175
:
176
177
178
|
179
ParamListPart
180
181
|
182
ParamList '','' ParamListPart
183
ParamListPart
184
:
185
ID '':'' TypeExpr
186
187
|
188
ID '':'' ID
189
190
Атрибуты
191
В языке Sim-nML атрибуты используются для описания свойств инструкций и режимов адресации. Описание каждого такого объекта может содержать произвольное число атрибутов. Атрибуты можно разделить на два класса: предопределенные атрибуты и пользовательские атрибуты. Описание предопределенных атрибутов приведено ниже.
192
Правила грамматики для атрибутов:
193
AttrDefList
194
:
195
196
197
|
198
AttrDefList AttrDef
199
AttrDef
200
:
201
ID ''='' AttrDefPart
202
203
|
204
SYNTAX ''='' ID ''.'' SYNTAX
205
206
|
207
SYNTAX ''='' AttrExpr
208
209
|
210
IMAGE ''='' ID ''.'' IMAGE
211
212
|
213
IMAGE ''='' AttrExpr
214
215
|
216
ACTION ''='' ID ''.'' ACTION
217
218
|
219
ACTION ''='' ''{'' Sequence ''}''
220
221
|
222
USES ''='' UsesDef
223
AttrDefPart
224
:
225
Expr
226
227
|
228
''{'' Sequence ''}''
229
Атрибут syntax
230
Атрибут syntax используется для описания ассемблерного кодирования инструкции или режима адресации. Значения данного атрибута должны иметь строковый тип. Можно выделить следующие основные варианты определения атрибута syntax:
231
1)Строковая константа — значение определяется посредством строковой константы. Например, “nop”.
232
2)Атрибут параметра — значение атрибута определяется как значение этого же атрибута syntax у одного из параметров описываемого объекта. Например, x.syntax.
233
3)Форматированная строка — значение атрибута определяется с помощью специальной конструкции format. Данная конструкция является аналогом оператора printf в языке программирования С. Например, format(“%5b”, r).
234
// TODO: добавить полное формальное описание конструкции format + описание транслчции данной конструкции в строковое выражение Java
235
Трансляция:
236
При трансляции данного атрибута в классе, соответствующем описываемому объекту создается метод со следующей сигнатурой:
237
public String syntax()
238
Для случая 1 из приведенного выше списка тело метода просто возвращает данную строковую константу. Для случая 2 метод возвращает результат вызова метода syntax соответствующего аргумента данного объекта. Такой аргумент должен содержаться в качестве поля в классе, соответствующем описываемому объекту. Для случая 3 метод возвращает результат трансляции конструкции format в строковое выражение языка Java.
239
Атрибут image
240
Атрибут image используется для описания бинарного кодирования описываемого объекта. Значения данного атрибута должны иметь строковый тип, причем допустимы только строки, содержащие символы «0», «1» и пробел. Пробелы используются для улучшения читаемости. Варианты определения атрибута image совпадают с вариантами определения атрибута syntax.
241
Трансляция:
242
Полностью аналогична трансляции атрибута syntax.
243
Атрибут action
244
Атрибут action используется для описания семантики выполнения инструкций. 
245
Трансляция:
246
// TODO: при трансляции атрибута action обратить внимание на то, что в некоторых спецификациях данные между соседними в дереве инструкциями передают с использованием переменных (var). Это надо корректно учитывать, так как по умолчанию при трансляции таких объектов предлагается создавать локальные переменные соответствующих методов. С другой стороны, использование переменных для передачи данных между операциями противоречит описанию языка, в котором сказано, что состояние переменных не сохраняется при переходе от одной инструкции к другой.
247
Атрибут uses
248
В текущей версии инструмента данный атрибут не рассматриваем.
249
Основные конструкции языка
250
251
h3. Конструкция let
252
253
Конструкция let используется для объявления констант. Константы обладают следующими свойтсвами:
254
1.Константы получают глобальную область видимости.
255
2.Константа может быть определена только один раз.
256
Правила грамматики для конструкции let:
257
LetDef 
258
:
259
LET ID ''='' LetExpr
260
LetExpr
261
:
262
ConstNumExpr
263
264
|
265
STRING_CONST
266
267
|
268
IF ConstNumExpr THEN LetExpr OptionalElseLetExpr ENDIF
269
270
|
271
SWITCH ''('' ConstNumExpr '')'' ''{'' CaseLetExprList ''}''
272
OptionalElseLetExpr
273
:
274
275
276
|
277
ELSE LetExpr
278
CaseLetExprList
279
:
280
CaseLetExprList1
281
282
|
283
CaseLetExprList1 DEFAULT '':'' LetExpr
284
CaseLetExprList1
285
:
286
CaseLetExprStat
287
288
|
289
CaseLetExprList1 CaseLetExprStat
290
CaseLetExprStat
291
:
292
CASE ConstNumExpr '':'' LetExpr
293
294
Примеры:
295
let REGS = 5
296
let byte_order = “big”
297
let PC = “NIA”
298
let SP = “GPR[29]”
299
Проблемы:
300
Не ясна семантика if и switch в том случае, когда определяемая величина не получает никакого значения, например
301
let c = if 0 then 0 endif
302
Ограничения:
303
На первом этапе разработки прототипа предлагается ограничить поддержку конструкции let только простыми вариантами (без if и switch). Сложные вариаты let практически не используются на практике (ни один из примеров спецификаций представленных на сайте языка не содержал таких конструкций), их ценность представляется сомнительной.
304
Трансляция:
305
Если LetExpr является ConstNumExpr, то вычисляется значение этого выражения. Для каждой определенной в спецификации константы определяется поле к классе ProcessorName следующего вида
306
	public static final <type> ID = LetExpr;
307
где <type> может принимать следующие значения:
308
String – в случае, если LetExpr является STRING_CONST
309
int – в случае, если LetExpr является числовым выражением и вычисленное  значение есть целое.число, убирающееся в int.
310
long – в случае, если LetExpr является числовым выражением и вычисленное  значение есть целое.число, не убирающееся в int.
311
float – в случае, если  LetExpr является числовым выражением и его вычисленное значение есть число с фиксированной или плавающей точкой, убирающееся в тип float.
312
double – в случае, если  LetExpr является числовым выражением и его вычисленное значение есть число с фиксированной или плавающей точкой, не убирающееся в тип float.
313
Ошибочные ситуации:
314
наличие целых чисел, которые «не убираются» в long
315
наличие чисел с плавающей точкой, которые «не убираются» в double
316
Конструкция type
317
Конструкция type используется для определения синонимов новых типов. Синонимы определяются на основе существующих стандартных типов:
318
bool: определяет булевский тип, имеющий два предопределенных значений false и true. При применении преобразования типов (смотри coerces) false отображается в 0, true – в 1. При обратном преобразовании 0 отображается в false, любое ненулевое значение отображается в true.
319
int(n):определяет интервал целых чисел 
320
card(n): определяет интервал натуральных чисел 
321
float: определяет число с плавающей точкой согласно стандарту IEEE754 // TODO: несоответствие грамматики и описания
322
fix(n, m):определяет число с фиксированной точкой, в котором n бит отводятся под мантису и m бит под экспоненту.// TODO: уточнить, что описано в документации
323
[n..m]: определяет интервал натуральных чисел (ограничение)
324
enum(): определяет перечислимый тип, где именованные константы принимают значения от 0 до n-1.Будет совпадать с типом card(ceiling())
325
Правила грамматики для конструкции type:
326
TypeSpec
327
:
328
TYPE ID ''='' TypeExpr
329
TypeExpr
330
:
331
BOOL
332
333
|
334
INT ''('' ConstNumExpr '')''
335
336
|
337
CARD ''('' ConstNumExpr '')''
338
339
|
340
FIX ''('' ConstNumExpr '','' ConstNumExpr '')''
341
342
|
343
FLOAT ''('' ConstNumExpr '','' ConstNumExpr'')''
344
345
|
346
''['' ConstNumExpr DOUBLE_DOT ConstNumExpr '']''
347
348
|
349
ENUM ''('' IdentifierList '')''
350
IdentifierList
351
:
352
ID
353
354
|
355
ID ''='' CARD_CONST
356
357
|
358
IdentifierList '','' ID
359
360
|
361
IdentifierList '','' ID ''='' CARD_CONST
362
363
Примеры:
364
type bit
365
 =
366
card ( 1 )
367
type byte
368
 =
369
card ( 8 )
370
type address
371
 =
372
card ( REGS )
373
type breakcode
374
 =
375
card (20 )
376
377
Проблемы:Моделирование чисел с фиксированной точкой.
378
Ограничения: в текущей реализации не рассматриваем случаи, когда определяется интервал, по мощности превосходящий максимальный соответствующий стандартный тип а Java. Например, исключаем из рассмотрения card (128).
379
Трансляция: 
380
Для каждого такого типа-синонима создается новый класс с именем ID, единственным полем которого будет переменная объемлющего типа, а методы будут обеспечивать корректность работы с этой переменной, контролируя невыход их множества допустимых значений. В случае нарушения данных ограничений метод должен выбрасывать исключение.
381
Необходимо учесть, что при трансляции операторов присваивания таким переменным, надо использовать методы set из соответствующих классов. Причем эти методы set должны в качестве параметров принимать так же номер строки и позицию в nml файле, по которой находится данный оператор присваивания. Эти данные используются отладки спецификаций в случае ошибок.
382
Перечисления транслируются в стандартные Java перечисления. Например, пусть есть перечисление:
383
type <name> = enum(id1 = val1, id2 = val2, …, idn = valn)
384
Оно транслируется в отдельный файл <name>.java, который содержит Java перечисление следующего вида:
385
public enum <name> {
386
	id1(val1), id2(val2), …, idn(valn)
387
}
388
Ошибочные ситуации:
389
390
h3. Конструкция mem
391
392
Конструкция mem используется для описания памяти моделируемого микропроцессора. Общий вид такого определения представлен ниже:
393
mem M [N, type] [optional-properties]
394
В этом определении, M – имя данного объекта памяти, N – количество ячеек памяти, и type – тип каждой такой ячейки памяти. Если тип не указан, то по умолчанию тип полагается равным card(8). Доступ к данным ячейкам памяти осуществляется по средствам оператора индексирования:M[0], M[1], … , M[n-1]. Опциональные параметры могут быть следующими:
395
alias – описывает новую память как синоним какойто части уже описанной памяти. В этом случае оба имени будут ссылать на одни и те же ячейки памяти, но могут интерпретировать их по разному. Например:
396
mem A[6, int(32)]
397
mem M[3, card(32)] alias = A[3]
398
В этом случае ячейки памяти, доступные по обращениям A[3], A[4], A[5], теперь могут быть доступны и по обращениям M[0], M[1], M[2] соответственно. Отличие заключается в том, что в случае обращений с использованием имени A содержимое ячейки интерпретируется как 32-ух разрядное знаковое число, в случае же, когда обращение идет по имени M, содержимое интерпретируется, как беззнаковое число.
399
Правила грамматики для конструкции mem:
400
Bit_Optr : BIT_LEFT Bit_Expr DOUBLE_DOT Bit_Expr BIT_RIGHT
401
MemorySpec
402
:
403
MEM ID ''['' SizeType '']'' OptionalMemVarAttr
404
SizeType
405
:
406
TypeExpr
407
408
|
409
ConstNumExpr
410
411
|
412
ConstNumExpr '','' TypeExpr
413
OptionalMemVarAttr
414
:
415
416
417
|
418
ALIAS ''='' MemLocation
419
MemLocation
420
:
421
ID Opt_Bit_Optr
422
423
|
424
ID ''['' NumExpr '']'' Opt_Bit_Optr
425
Opt_Bit_Optr
426
:
427
428
429
|
430
Bit_Optr
431
Bit_Optr
432
:
433
BIT_LEFT Bit_Expr DOUBLE_DOT Bit_Expr BIT_RIGHT
434
435
// TODO: не ясна семантика Opt_Bit_Expr в грамматики для конструкции
436
 mem, в примерах использование именно такой формы тоже не было встречено.
437
Примеры:
438
	mem A[6, int(32)]
439
	mem M[3, card(32)] alias = A[3] 
440
Проблемы:
441
Ограничения:
442
Трансляция:
443
Анализ спецификаций на языке Sim-nML позволил выявить, что конструкция mem может быть использована для двух различных целей. Во-первых, она может использоваться для описания памяти моделируемого микропроцессора. В этом случае число ячеек памяти в описании довольно большое (N >> 1). Необходимо найти описание с максимальным числом ячеек, именно оно будет транслироваться в класс, моделирующий память. При трансляции данного описания создается класс ProcessorNameMemory, который является наследником абстрактного класса Memory из библиотеки поддержки трансляции. Класс ProcessorNameMemory имеет следующий вид:
444
class ProcessorNameMemory {
445
	public static final SIZE = <N>;
446
	protected HashMap(Long, <type>) memoryHashMap = new HashMap(Long, <type>)();
447
}
448
Для всех других описаний памяти, которые являются синонимами основной памяти (используют alias <имя основной памяти>), в атрибутах action для операций необходимо изменять обращения по этим именам на обращения по имени основной памяти.
449
Второй класс описаний памяти составляют описания, которые имеют небольшое число ячеек (обычно 1 или 2). Такие описания используются в качестве локальных переменных при описании атрибутов action для инструкций. Все такие описания при трансляции запоминаются. Затем при трансляции атрибутов action в методы инструкций, для каждой запомненной памяти, по которой присутствует обращение в данном атрибуте, вводится локальная переменная соответствующего типа. Все обращения по данным элементам памяти заменяются при трансляции на обращения к данной переменной. Например,
450
	mem tmp_signed_byte [ 1 , int (32) ]
451
452
	action = {
453
		 tmp_signed_byte = 31
454
455
	}
456
При трансляции атрибута action получаем получим:
457
	public void execute(...) {
458
		int tmp_signed_byte
459
460
	}
461
462
// TODO: определить абстрактный класс Memory
463
464
Ошибочные ситуации:
465
466
h3. Конструкция reg
467
468
Конструкция reg используется для описания регистров микропроцессора. Общая форма описания регистров представлена ниже:
469
reg R [N, type] [optional-properties]
470
В представленном определении R – имя регистрового файла, N – опциональный параметр, показывающий количество регистров в регистровом файле и type – тип каждого регистра. Если параметр N не указан, то по умолчанию он полагается равным 1.Доступ к регистрам данного регистрового файла осуществляется посредством оператора индексирования — R[0], R[1], …, R[N-1]. Определение регистров может иметь следующие опциональные атрибуты:
471
Ports: позволяет указать число портов чтения и записи для данного регистрового файла. Например:
472
reg R[16, int(8)] port = 3, 2
473
В представленном примере регистровый файл R имеет 3 порта для записи и 2 порта для чтения. Кроме того, каждый регистр в данном регистровом файле имеет 2 порта для чтения, так же как и весь регистровый файл, и один порт для записи. Порты чтения и записи для регистров рассматриваются в качестве ресурсов и используются для определения зависимостей между инструкциями.
474
Initial: позволяет указать начальное значение для описанных регистров. Например:
475
reg R[1, card(32)] initial = 100
476
Правила грамматики для конструкции reg:
477
RegisterSpec
478
:
479
REG ID ''['' SizeType '']'' OptionalRegAttr
480
OptionalRegAttr
481
:
482
483
484
|
485
PortsDef
486
487
|
488
InitialDef
489
490
|
491
PortsDef InitialDef
492
493
|
494
InitialDef PortsDef
495
PortsDef
496
:
497
PORTS ''='' CARD_CONST '','' CARD_CONST
498
InitialDef
499
:
500
INITIALA ''='' ConstNumExpr
501
502
Примеры:
503
	reg GPR [2 ** REGS, signed_long]
504
	reg LO [1, signed_long]
505
	reg NIA [1, long]
506
Проблемы:
507
Ограничения:
508
Трансляция:
509
Для каждого описанного регистрового файла создается класс RegisterFileName, который является наследником абстрактного класса библиотеки поддержки трансляции Register. Класс Register содержит следующие поля и методы:
510
class Register {
511
	public static final int WRITE_PORTS = 1;
512
	public static final int READ_PORTS = 1;
513
	...
514
}
515
Класс RegisterFileName содержит следующие поля и методы:
516
class RegisterFileName {
517
	public static final int READ_PORTS = <read_ports>;
518
	protected <type> value = <init_value>;
519
	...
520
}
521
Так же в класс ProcessorName добавляются следующие поля и методы:
522
	public static final int RegisterFileName_WRITE_PORTS = <write_ports>;
523
	protected RegisterFileName <some_uniq_name> [] = {
524
		new RegisterFileName(),
525
		...
526
	}
527
Причем количество элементов в массиве RegisterFileName равно N.
528
Ошибочные ситуации:
529
530
h3. Конструкция var
531
532
Конструкция var используется для определения временных переменных. Типичная конструкция определения временной переменной выглядит следующим образом:
533
var TEMP[N, type]
534
В приведенном выше определении TEMP – имя массива временных переменных, N – количество переменных в определенном массиве и type – тип каждой переменной в массиве. Если параметр N не определен, то по умолчанию он полагается равным 1. Доступ к переменным осуществляется посредством оператора индексирования — TEMP[0], TEMP[1], …, TEMP[N-1]. Важно отметить, что значения временных переменных не сохраняются при переходе от одной инструкции к другой.
535
// COMMENT: по всей видимости переменные были введены в язык для прекращения нецелевого использования конструкций определения памяти для введения временных данных. Смотри второй класс конструкций определения памяти в разделе «трансляция» описания конструкции mem.
536
Правила грамматики для конструкции var:
537
// TODO: противоречие между текстовым описанием и грамматикой.
538
VarSpec
539
:
540
VAR ID ''['' SizeType '']'' OptionalMemVarAttr
541
542
Примеры:
543
	var amod[1, card(8)]
544
	var carry[1, card(1)]
545
	var op1[1, int(32)]
546
Проблемы:
547
Ограничения:
548
Трансляция:
549
Трансляция выполняется аналогично второму классу конструкций определения памяти. Описание приводится в разделе «трансляция» описания конструкции mem.
550
Ошибочные ситуации:
551
Конструкция mode
552
Конструкция mode используется для спецификации механизмов адресации. Основу данного описания этих механизмов составляют два вида конструкций: «И»-правила и «ИЛИ»-правила.
553
«ИЛИ»-правила используются для описания логически связанной группы механизмов адресации. С помощью «ИЛИ»-правила можно задать группе таких механизмов общие атрибуты. Общий вид «ИЛИ»-правила следующий:
554
555
556
«И»-правила используются для описания листовых элементов в дереве механизмов адресации. Общий вид «И»-правила следующий:
557
558
559
Правила грамматики для конструкции mode:
560
ModeRuleSpec
561
:
562
MODE ID ModeSpecPart
563
ModeSpecPart
564
:
565
AndRule OptionalModeExpr AttrDefList
566
567
|
568
OrRule
569
OptionalModeExpr
570
:
571
572
573
|
574
''='' Expr
575
Примеры:
576
Проблемы:
577
Ограничения:
578
Трансляция:
579
Трансляция дерева «И»-«ИЛИ» правил проводится идентично как для инструкций, так и для режимов адресации. Подробные описания общих концепций трансляции приведены в разделе «Трансляция» описания конструкции op. Эти положения верны и при описании режимов адресации. Специфические моменты при трансляции этих описаний отражены ниже.
580
У и правил конструкции mode может присутствовать дополнительный опциональный элемент, который вычисляет значение параметра, передающегося данным способом адресации. Для каждого правила, обладающего таким элементом, в соответствующем классе создается тело метода getValue() на основе описания данного элемента. Метод возвращает оттранслированное выражение записанное в правиле после знака равенства.
581
Ошибочные ситуации:
582
583
h3. Конструкция op
584
585
Конструкция op используется для описания системы команд моделируемого процессора.
586
Правила грамматики для конструкции op:
587
OpRuleSpec
588
:
589
OP ID OpRulePart
590
OpRulePart
591
:
592
AndRule AttrDefList
593
594
|
595
OrRule
596
597
Примеры:
598
Проблемы:
599
Ограничения:
600
Трансляция:
601
Общие положения при трансляции древовидной структуры «И»-«ИЛИ» правил заключаются в следующем. Для каждого правила создается класс. Классы, соответствующие элементам из правых частей «ИЛИ» правил связываются с классом, соответствующим элементу в левой части, отношением наследования. Каждый класс, соответствующий элементу из списка параметров в «И»-правиле, связывается с классом, соответствующим элементу из левой части правила, отношением агрегации. На примере ниже продемонстрированы данные принципы с использованием нотации UML для отображения зависимостей между классами.
602
op instruction(inst alu_op)
603
op alu_instruction = add | sub
604
В каждом из этих классов создаются методы, соответствующие атрибутам. Механизм трансляции атрибутов подробно описан в разделе «Атрибуты». Имена создаваемых классов должны содержать некоторый служебный суффикс, что будет говорить о служебном внутреннем использовании данных классов. 
605
Для каждого элемента из списка параметров «И» правила в соответствующем классе создаются поле. Для класса также создается конструктор с сигнатурой, соответствующей данному правилу, который инициализирует эти поля.
606
// TODO: посмотреть информацию про модификаторы доступа классов, пакетов для защиты служебных классов от некорректного использования.
607
Далее, для каждого листового элемента в дереве инструкций создается еще один класс, который наследуется от класса Instruction (соответствует корню дерева). Эти классы распределяются по пакетам в соответствии со структурой дерева. Для каждого не листового узла дерева создается отдельный пакет, куда вложены все пакеты и классы, соответствующие потомкам данного узла.
608
Ошибочные ситуации: