File: interpreter.lyx

package info (click to toggle)
adonthell 0.3.8-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,416 kB
  • sloc: cpp: 50,659; sh: 5,142; python: 3,307; makefile: 338; lex: 216; sed: 16
file content (454 lines) | stat: -rw-r--r-- 10,060 bytes parent folder | download | duplicates (9)
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
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
#This file was created by <root> Fri Mar 31 14:16:48 2000
#LyX 1.0 (C) 1995-1999 Matthias Ettrich and the LyX Team
\lyxformat 2.15
\textclass article
\language default
\inputencoding default
\fontscheme default
\graphics default
\paperfontsize default
\spacing single 
\papersize Default
\paperpackage a4wide
\use_geometry 0
\use_amsmath 0
\paperorientation portrait
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\defskip medskip
\quotes_language english
\quotes_times 2
\papercolumns 1
\papersides 1
\paperpagestyle default

\layout Section

The Interpreter
\layout Subsection

What does the Interpreter do?
\layout Standard

Unlike the name 
\emph on 
interpreter
\emph default 
 implies, it does not interprete scripts, it merely is the environment for
 scripts to run in.
 That means, in a way scripts interprete themselves.
 I'll explain that shortly, for now lets concentrate on the interpreter.
\layout Standard

The interpreters purpose is to provide a common environment for self-interpretin
g scripts.
 That means, it can load scripts from a file, and afterwards execute them.
 It furthermore offers a local storage for temporary data and has a interface
 to access user-defined data as well.
\layout Subsection

How to use the Interpreter
\layout Standard

Since there is not much the interpreter does, it is easy and straightforward
 to use:
\layout Standard

Create a new instance, call 
\family typewriter 
load()
\family default 
 to load the desired script and 
\family typewriter 
run()
\family default 
 to start execution of the script.
 That's all there is to it.
\layout Subsection

The Interpreter's interface
\layout Standard
\noindent 

\family typewriter 
interpreter ();
\layout Standard

Create a new instance of the interpreter
\newline 

\layout Standard
\noindent 

\family typewriter 
interpreter (const char* script, void* data);
\layout Standard

Creates a new, already initialized, instance of the interpreter
\newline 

\layout Standard


\family typewriter 
script
\family default 
 is the filename of the script to load
\layout Standard


\family typewriter 
data
\family default 
 points to a object that is to be manipulated from within the script
\newline 

\layout Standard

The interpreter is now ready to run the script, there is no need to call
 
\family typewriter 
load()
\family default 
 any more.
\newline 

\layout Standard
\noindent 

\family typewriter 
u_int8 load (const char*);
\layout Standard

Load a script from file
\newline 

\layout Standard


\family typewriter 
script
\family default 
 is the filename of the script to load
\layout Standard


\family typewriter 
returns
\family default 
 1 on success, 0 on failure
\newline 

\layout Standard
\noindent 

\family typewriter 
s_int32 run ();
\layout Standard

Executes the script.
 
\newline 

\layout Standard


\family typewriter 
returns
\family default 
 whatever value the 
\noun on 
Return
\noun default 
 command of your script passes back.
\newline 

\layout Standard
\noindent 

\family typewriter 
void *user_data;
\layout Standard

Points to an object you can manipulate from within a script.
\layout Section

The Script
\layout Subsection

What does a Script do?
\layout Standard

Nothing and everything.
 A script is a series of 
\emph on 
commands, 
\emph default 
defined by a unique id (a simple integer) followed by their optional parameters.
 On it's own, a script is as useful as the interpreter, that is it's good
 for nothing.
 Only in combination with the interpreter, it becomes useful.
 
\layout Standard

A bit further up I said scripts would interprete themselves, what do they
 need the interpreter for then? Basically, each command does not only exist
 as a number and some parameters in a script, but also as a class that containes
 the commands execution code.
 You guessed it, commands will be explained in detail a bit later on.
\layout Subsection

What happens when a Script is loaded?
\layout Standard

This will answer the question of the interpreters use.
 For each command within the script, a instance of that commands class is
 allocated and initialized with the arguments specified in the script.
 That means the interpreter creates actual code from a mere binary file,
 at the programs runtime.
 Of course it can't create any 
\emph on 
new
\emph default 
 code, only arrange predefined code snippets (the commands) in a way that
 they do something useful.
 That is probably as dynamic as you can make a compiled c++ program.
\layout Subsection

How is the Script executed?
\layout Standard

When you run the interpreter, it simply executes the commands, beginning
 with the first, until it hits the already mentioned 
\noun on 
Return
\noun default 
 command.
 That alone isn't very exciting, but there are two things that make the
 whole execution process a bit more interesting.
\layout Standard

First of all, you can change the order in which commands are executed from
 
\emph on 
within
\emph default 
 a command.
 More on this later.
\layout Standard

And second, you can have multiple 
\noun on 
Return
\noun default 
's in your script.
 That means, once the interpreter has stopped executing commands, you can
 invoke it again, letting it continue with the command following immediately
 after the return.
\layout Subsection

The Script's file format
\layout Standard
\added_space_top 0.3cm \added_space_bottom 0.3cm \align center \LyXTable
multicol5
6 2 0 0 -1 -1 -1 -1
1 1 0 0
1 0 0 0
1 1 0 0
1 1 0 0
0 1 0 0
0 1 0 0
2 1 0 "8cm" ""
4 1 1 "" ""
0 2 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""
0 2 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""
0 2 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""
0 2 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""
0 2 1 0 0 0 0 "" ""
0 4 1 0 0 0 0 "" ""


\series bold 
File Header:
\newline 
8 bytes
\series default 

\newline 
Length of the script in bytes, that is file_length - 8
\newline 
4 bytes
\newline 
Number of commands within the script
\newline 
4 bytes
\newline 

\series bold 
Commands:
\series default 

\newline 

\newline 
Id
\newline 
4 bytes
\newline 
[Parameters]
\newline 
[4*n bytes]
\layout Standard

A side note on a commands parameters: as we learn later on, each command
 is responsible for extracting it's parameters itself from the script file,
 so the only limitation regarding a commands parameters is that they have
 to be aligned on a 32 bit boundary.
 Apart from that, any number and type of parameters is allowed.
\layout Section

The Commands
\layout Subsection

What does a Command do?
\layout Standard

As we have seen, in the end everything boild down to commands.
 Each command contains code that is invoked from the interpreter.
 What that code does is completely up to you, which means with the right
 commands put together in a script you can do nearly everything, well at
 least nearly everything you can do with c++.
\layout Standard

To be more precise, each command has a entry point named 
\family typewriter 
run()
\family default 
, that is called by the interpreter.
 From there on, you are free to call other functions, access the user data
 passed to the interpreter or any other data that is (globally) accessible.
 You can even change the interpreters 
\emph on 
program counter
\emph default 
 (pc), that points to the command to be executed next.
\layout Subsection

How to implement a Command
\layout Standard

To make all that work, there are a few requirements any of your commands
 must meet.
\layout Subsubsection

Command base class
\layout Standard

Each command has to be derived from a comman base class, namely 
\family typewriter 
command
\family default 
, defined in 
\emph on 
interpreter.h
\emph default 
.
 This base class has two pure virtual functions you need to overwrite: 
\newline 

\newline 

\family typewriter 
virtual void init(s_int32* buffer, u_int32& index, void* data) = 0;
\layout Standard

This is used to initialize your commands parameters when the interpreter
 loads your script.
\newline 

\layout Standard


\family typewriter 
buffer
\family default 
 contains a copy of the script file
\layout Standard


\family typewriter 
index
\family default 
 points to the start of your commands first parameter within 
\family typewriter 
buffer
\family default 
.
 You have to assure that it points to the start of the next command once
 you finished with reading your commands parameters.
 That might mean a bit more work for you, but since the interpreter knows
 nothing of your command and its parameters, it's the only possible way.
\layout Standard


\family typewriter 
data
\family default 
 points to the userdefined chunk of data you may have passed to the interpreter
\newline 

\newline 

\family typewriter 
virtual s_int32 run (u_int32& pc, void* data) = 0;
\layout Standard

That is the entry point to your commands actual code.
\newline 

\layout Standard


\family typewriter 
pc
\family default 
 is a reference to the interpreters program counter.
 Usually you need not touch it, but if you like to continue your script
 with another but the next command, you can change it.
 Note that at the point your command starts executing, 
\family typewriter 
pc
\family default 
 points already to the following command.
\layout Standard


\family typewriter 
data
\family default 
 points to the userdefined chunk of data you may have passed to the interpreter
\newline 
 
\layout Subsubsection

Register the Command
\layout Standard

By deriving all commands from one base class, we enable the interpreter
 to remain ignorant of the different commands.
 It needs only to know that base class to run any command derived thereof.
 What it can't do yet is to create an instance of a command when reading
 its Id from the script file.
 Therefore, for each command a function has to be written that returns a
 new instance of that command.
 A pointer to that function is then stored in an array and, what surprise,
 can be accessed with its Id, enabling the interpreter to instanciate commands
 without knowing anything about them, except their Id.
\the_end