Static TypeScript
1
Static TypeScript
56
2
57
3
An Implementation of a Static Compiler for the TypeScript Language
58
4
59
5
60
6
Thomas Ball
Peli de Halleux
Michal Moskal
61
7
Microsoft Research
Microsoft Research
Microsoft Research
62
8
Redmond, WA, United States
Redmond, WA, United States
Redmond, WA, United States
63
9
tball@
jhalleux@
mimoskal@
64
10 Abstract
11
12 While the programming of microcontroller-based embed-
13 dable devices typically is the realm of the C language, such
14 devices are now finding their way into the classroom for CS
15 education, even at the level of middle school. As a result, the
16 use of scripting languages (such as JavaScript and Python)
17 for microcontrollers is on the rise.
18
We present Static TypeScript (STS), a subset of TypeScript
19 (itself, a gradually typed superset of JavaScript), and its com-
20 piler/linker toolchain, which is implemented fully in Type-
21 Script and runs in the web browser. STS is designed to be use-
22 ful in practice (especially in education), while being amenable
23 to static compilation targeting small devices. A user's STS
24 program is compiled to machine code in the browser and
25 linked against a precompiled C++ runtime, producing an ex-
26 ecutable that is more efficient than the prevalent embedded
27 interpreter approach, extending battery life and making it
28 possible to run on devices with as little as 16 kB of RAM
29 (such as the BBC micro:bit).
30
This paper is primarily a description of the STS system
31 and the technical challenges of implementing embedded
32 programming platforms in the classroom.
65
66
67
68
69
70
71
72
(a)
(b)
73
74
Figure 1. Two Cortex-M0 microcontroller-based educational 75
devices: (a) the BBC micro:bit has a Nordic nRF51822 MCU 76
with 16 kB RAM and 256 kB flash; (b) Adafruit's Circuit Play- 77
ground Express () has an 78
Atmel SAMD21 MCU with 32 kB RAM and 256 kB flash.
79
80
81
girls, increases confidence in both students and teachers, and 82
makes lessons more fun [2, 16].
83
To keep costs low for schools, these devices typically em- 84
ploy 32 bit ARM Cortex-M microcontrollers (MCUs) with 85
16-256kB of RAM and are programmed using an external 86
computer (usually a laptop or desktop). Programming such 87
33 Keywords JavaScript, TypeScript, compiler, interpreter, mi34 crocontrollers, virtual machine
35
36
37 1 Introduction
38 Recently, physical computing has been making headway in 39 the classroom, engaging children to build simple interactive
40 embedded systems. For example, Figure 1(a) shows the BBC
41 micro:bit [1], a small programmable Arduino-inspired com-
42 puter with an integrated 5x5 LED display, several sensors
43 and Bluetooth Low Energy (BLE) radio technology. The de-
44 vice first rolled out in 2015 to all year 7 students (age 10 to
45 11) in the UK and has since gone global, with four million 46 units distributed worldwide to date via the micro:bit Educa-
47 tion Foundation (). Figure 1(b) shows a
48 different educational device featuring RGB LEDs: Adafruit's
49 Circuit Playground Express (CPX).
50
Research suggests that using such devices in computer
51 science education increases engagement, especially among
52
53 MPLR 2019, Under submission,
54
.
devices in a classroom presents a number of technical chal- 88
lenges:
89
(1) the selection/design of an age-appropriate program- 90
91
ming language and environment;
(2) classroom computers running outdated operating sys- 92
tems, having intermittent and slow internet connec- 93
94
tivity, and locked down by school IT administrators,
which makes native app installation difficult;
95
(3) the transfer of the student's program from the com- 96
puter to the device, where it can run on battery power 97
98
(as many projects embed the device in an experiment
or "make").
99
100
With respect to these challenges, there are various embed- 101
ded interpreters for popular scripting languages, such as 102
JavaScript (JerryScript [8, 15], Duktape [22], Espruino [23], 103
mJS [20], and MuJS [19]) and Python (MicroPython [9] and 104
its fork CircuitPython [12]). The interpreters run directly on 105
the MCU, requiring just the transfer of program text from the 106
host computer, but forego the benefits of advanced optimiz- 107
ing JIT compilers (such as V8) that require about two orders 108
of magnitude more memory than is available on MCUs.
109
55
1
110
MPLR 2019, Under submission,
Thomas Ball, Peli de Halleux, and Michal Moskal
111
? the STS compiler generates surprisingly efficient and 166
112
compact machine code, which unlocks a range of ap- 167
113
plication domains such as game programming for low- 168
114
resource devices such as those in Figure 2, all of which 169
115
were enabled by STS.
170
116 117 118 119 120 121 122 123 124 125 126 127 128
129 Figure 2. Three microcontroller-based game handhelds with 130 160x120 color screens. These boards use ARM's Cortex-M4F 131 core: the ATSAMD51G19 (192kB RAM, running at 120Mhz) 132 and STM32F401RE (96kB RAM, running at 84Mhz).
133
Deployment of STS user programs to embedded devices 171
does not require app or device driver installation, just access 172
to a web browser. Compiled programs appear as downloads, 173
which are then transferred manually by the user to the device, 174
which appears as a USB mass storage device, via file copy 175
(or directly through WebUSB, an upcoming standard for 176
connecting websites to physical devices).
177
The relatively simple compilation scheme for STS (pre- 178
sented in Section 3) leads to surprisingly good performance 179
on a collection of small JavaScript benchmarks, often com- 180
parable to advanced, state of the art JIT compilers like V8, 181
with orders of magnitude smaller memory requirements (see 182
Section 4). It is also at least an order of magnitude faster 183
than the embedded interpreted approach. A novel aspect of 184
evaluation is a comparison of different strategies for dealing 185
with field/method lookup spanning classes, interfaces, and 186
dynamic maps.
187
188
134
135
Unfortunately, such embedded interpreters are between
136 one and three orders of magnitude slower than V8 (see Sec-
137 tion 4), affecting responsiveness and battery life. Even more
138 importantly, due to the representation of objects in memory
139 as dynamic key-value mappings, the memory footprint can
140 be several times that of an equivalent C program. This can
141 severely limit the applications that can be deployed on low-
142 memory devices such as the micro:bit (16 kB RAM) and CPX
143 (32 kB RAM).
144
1.1 Static TypeScript
145
146 As an alternative to embedded interpreters, we present Static 147 TypeScript (STS), a syntactic subset of TypeScript,[3] sup148 ported by a compiler (written in TypeScript) that generates 149 machine code that runs efficiently on MCUs in the target 150 RAM range of 16-256kB. The design of STS and its compiler 151 and supporting runtime were dictated primarily by the above 152 three challenges. In particular:
153
? STS eliminates most of the "bad parts" of JavaScript;
154
following StrongScript [14], STS uses nominal typing
155
for statically declared classes and supports efficient
156
compilation of classes using classic techniques for v-
157
tables.
158
? the STS toolchain runs offline, once loaded into a web
159
browser, without the need for a C/C++ compiler ? the
160
toolchain, implemented in TypeScript, compiles STS
1.2 MakeCode: Easy Embedded for Education
189
STS is the core language supported by the MakeCode Frame- 190
work.1 MakeCode enables creation of custom programming 191
experiences for MCU-based devices. Each MakeCode experi- 192
ence (we often call them editors, though they also bundle a 193
simulator, APIs, tutorials, documentation, etc.) targets pro- 194
gramming of a specific device or device class via STS. [7]
195
Most MakeCode editors are deployed primarily as web 196
apps, including a full-featured text editor for developing STS 197
198
programs based on Monaco (the editor component of Visual
Studio Code), as well as a graphical programming interface 199
based on Google's Blockly framework (STS metadata in com- 200
ments defines the mapping from STS APIs to Blockly and 201
MakeCode translates between Blockly and STS).
202
The MakeCode editors, including the primary coding ex- 203
periences for BBC micro:bit and for Adafruit CPX,2 have 204
205
been used by millions of students and teachers worldwide
to date.
206
STS supports the concept of a package, a collection of STS, 207
C++ and assembly files, that also can list other packages as 208
dependencies. This capability has been used by third parties 209
to extend the MakeCode editors, mainly to accommodate 210
hardware peripherals for various boards.3 Notably, most 211
212
of the packages avoid pitfalls of unsafe C/C++ completely
and are authored solely in STS, due to the efficiency of the 213
STS compiler and the availability of low-level STS APIs for 214
215
161
to Thumb machine code and links this code against
1See . The framework, along with many editors, is
216
162
a pre-compiled C++ runtime in the browser, which
open source under MIT license, see .
217
163
is often the only available execution environment in
2See and .
218
164
schools.
3For example for micro:bit, see
219
165
2
220
Static TypeScript
MPLR 2019, Under submission,
221
276
222
277
223
278
224
279
225
280
226
281
227
282
228
283
229
284
230
285
231
286
232
287
233
288
234
289
235
290
236
291
237
292
238
293
239
294
240
295
241
296
242
297
243 Figure 3. MakeCode Arcade editor. The left pane is the simulator for the arcade device; the middle pane is the categories of 298
244 APIs available in the editor; the right pane is the Monaco editor with STS user code for a platformer game (. 299
245 com/85409-23773-98992-33605).
300
246
The toggle on top is used switch between Blocks and Static TypeScript (labelled JavaScript for marketing reasons).
301
247
302
248 accessing hardware via digital/analog pins (GPIO, PWM and
249 servos) and serial protocols (I2C and SPI).
250
Figure 3 shows the MakeCode Arcade editor created for
251 programming the handheld gaming devices from Figure 2
252 (in fact, the STS program shown in the editor is the one
253 deployed to the three devices - it is a simple platformer
254 game). MakeCode Arcade includes a game engine written
255 almost completely in STS, and thus places high requirements
256 on code efficiency to achieve pleasing visual effects at high
257 frame rates. The game engine includes the game loop, stack
258 of event contexts, physics engine, text and line drawing,
259 as well as game-specific frameworks (eg., for platformer
260 games), in all about 10,000 lines of STS code, with only the
261 most basic image-blitting primitives implemented in C++.
262 The games built with Arcade run either in the web browser
263 (on desktop or mobile), or on various models of dedicated
264 hardware featuring a 160x120 pixel 16 color screen and an
265 MCU running at around 100MHz with around 100kB of RAM.
266
The primary contribution of this paper is a description of
267 a widely deployed system and ways in which it addresses
268 the classroom-specific problems listed above.
269
270
271 2 Static TypeScript (STS)
272 TypeScript [3] is a gradually-typed [18] superset of the Java273 Script language. This means that every JavaScript program 274 is a TypeScript program and that types can be optionally
added, as needed, which enables better IDE support and error 303
checking for larger JavaScript programs. By design, Type- 304
Script provides no type soundness guarantees. Object types 305
provide a unification of maps, functions, and classes; struc- 306
tural subtyping between object types defines substitutability 307
and compatibility checks. Type erasure (and minor syntactic 308
transformations) yields a raw JavaScript program.
309
STS is a subset of TypeScript that excludes many of the 310
highly dynamic parts of JavaScript: the with statement, the 311
eval expression, prototype-based inheritance, the this 312
pointer outside classes, the arguments keyword, and the 313
apply method. STS retains features such as dynamic maps, 314
but keeps them separate from the nominal class abstraction. 315
Such restrictions are acceptable because most beginners' 316
programs are quite simple, and there are very few existing 317
JavaScript or TypeScript libraries in the embedded space, so 318
the chance of these using JavaScript features such as monkey 319
patching is small.
320
Our goal is not to grow STS to the point of supporting all 321
of TypeScript. Instead, we follow the pragmatic approach of 322
adding features useful in embedded context, as guided by 323
user feedback.
324
In contrast to TypeScript, where all object types are bags 325
of properties, STS has at runtime four kinds of unrelated 326
object types:
327
328
329
275
3
330
MPLR 2019, Under submission,
Thomas Ball, Peli de Halleux, and Michal Moskal
331
1. a dynamic map type has named (string-indexed) prop-
STS supports calling functions from C++ to STS and vice 386
332
erties that can hold values of any type;
versa. To simplify this process, STS uses a simple code- 387
333
2. a function (closure) type;
generation scheme, where a special comment on a C++ func- 388
334
3. a class type describes instances of a class, which are tion indicates that it should be exported to STS (//% ), as 389
335
treated nominally, via an efficient runtime subtype well as to Blockly (//% block). A build step parses the 390
336
check on each field/method access, as described below; C++ code in search of these comments, it also collects the 391
337
4. an array (collection) type.
prototypes (signatures) of these functions, so appropriate 392
338
conversions can be generated when calling them. For exam- 393
339 In this sense, STS is much closer to spirit to Java and C# in
ple:
394
340 their treatment of types as "protectors of abstractions", unlike
// source C++ code:
395
341 JavaScript which allows a much more freeform treatment of
namespace control {
396
342 an object's role. As discussed in Section 3.4, runtime type
/** Register an event handler */
397
343 tags are used to distinguish the different kinds of built-in
//% block
398
344 object types listed above (as well as primitives like boxed
void onEvent(int eventType, Action handler) {
399
345 numbers and strings).
// arrange for pxt::runAction0(handler)
400
346
As in TypeScript, type casts do not generate any code, and
347 thus always succeed. Instead, STS protects the nominal class
348 abstraction at the point of field/method access. Just as x.
// to be called when eventType is triggered } }
401 402 403
349 f causes a runtime error in JavaScript when x == null,
// generated TypeScript:
404
350 executing (x as T).f will cause a runtime error in STS
declare namespace control {
405
351 if T is a class with field f, and the dynamic type of x is not
/** Register an event handler */
406
352 a nominal subtype of T. If T is an interface, any, or some
//% block shim=control::onEvent
407
353 complex type (eg., union or intersection), then the field will
function onEvent(eventType: number,
408
354 be looked up by name regardless of dynamic type of x.
355
Other abstractions are also protected at runtime, as in
}
handler: () => void) : void;
409
410
356 JavaScript: for example, making a function call on something
The C++ namespaces and function names are mapped di- 411
357 that is not of function type. Currently, it is an error to dy- rectly to their STS equivalents and the documentation com- 412
358 namically add a new property to any type other than the
ment is copied verbatim. The comment //% block, which 413
359 map type. Restrictions to the dynamic JavaScript semantics
indicates that the function should be exposed as a Blockly 414
360 may be lifted in the future, depending on user feedback. To
graphical block is also copied. There are many other possi- 415
361 date, these restrictions have generated no concerns among
ble comments controlling the look and feel of the graphical 416
362 our user community (both educators and developers).
equivalent. The STS function also gets an additional shim 417
363
STS primitive types are treated according to JavaScript
annotation, which indicates the name of the corresponding 418
364 semantics. In particulars, all numbers are logically IEEE 64
C++ function (in some cases the STS declaration is written 419
365 bit floating point, but 31-bit signed tagged integers are used
by hand, and the name of the C++ function does not have to 420
366 where possible for performance. Implementation of opera- match the STS function).
421
367 tors, like addition or comparison, branch on the dynamic 368 types of values to follow JavaScript semantics, with the fast
The C++ types are mapped to STS types. Since in STS all 422 numbers are conceptually doubles4, the C++ int is mapped 423
369 integer path hand-implemented in assembly.
to STS number. When the C++ function is called, the STS 424
370
The design goal of STS to be both syntactic and semantic
compiler makes sure to convert the value passed to an integer. 425
371 subset of TypeScript, by which we mean that if a program
Other C++ integer types (eg., uint16_t) are supported in 426
372 compiles successfully in STS, it will have the same semantics
a similar way. The C++ Action type represents a reference 427
373 as the TypeScript program, or it will crash (in the circum- to a closure, which can be called with pxt::runAction0 428
374 stances listed above).
().
429
375
While class methods are not supported directly, regular 430
376
functions can be used to implement objects. For example:
431
377 2.1 C++ Interop
378
STS programs running on MCUs are supported by a runtime
379
implemented in C++, C, and assembly. The runtime imple-
380
ments language primitives (operators, collections, support 381 for classes, dynamic maps, etc.), as well as allows access to the
382
underlying device hardware. The runtime can be extended
383
by packages as explained in Section 2.2.
384
// C++
432
typedef BoxedBuffer *Buffer;
433
namespace BufferMethods {
434
//%
435
int getByte(Buffer self, uint32_t i) {
436
return i < self->len ? self->data[i] : 0;
437
4There is some support to store numbers as integers of various sizes to save
438
memory, but it only applies to storage, not intermediate computations.
439
385
4
440
Static TypeScript
MPLR 2019, Under submission,
441
}
conflicts due to lack of namespace enforcement is low, and it 496
442 }
allows for fitting new APIs naturally in existing namespaces. 497
443
498
444 // TypeScript
445 interface Buffer {
446
//% shim=BufferMethods::getByte
getByte(i: number); 447
} 448
449
All functions in BufferMethods namespace must take
450 Buffer as first argument and are exposed as members of
451 the Buffer class on the STS side. When such members
452 are called, the STS compiler will make sure the first argu-
453 ment is non-null and a subtype of Foo. These interfaces
3 Compiler and Runtime
499
The STS compiler and toolchain (linker, etc.) are written 500
solely in TypeScript. There currently is no support for sepa- 501
rate compilation of STS files: STS is a whole program com- 502
piler (with support for caching precompiled packages, which 503
includes the C++ runtime). The STS device runtime is mainly 504
written in C++ and includes a bespoke garbage collector. As 505
mentioned before, it is not a goal to generalize STS to support 506
full JavaScript.
507
508
454 are conceptually better understood as non-extensible classes 455 with opaque representation, that is they cannot be imple456 mented by regular classes, and member resolution is static. 457 The interface syntax was chosen because TypeScript allows 458 extending interfaces with new methods across files. We allow 459 such additions, provided the new methods have the shim 460 =... annotation described above, or alternatively an analog 461 annotation specifying a TypeScript, not C++, replacement 462 function. This usually only concerns authors of advanced 463 C++ packages (see below).
464
465 2.2 Packages
466 STS supports multiple input files. It also supports Type467 Script namespace syntax for scoping. Files do not intro468 duce scopes and JavaScript modules are currently not sup469 ported. The input files come from one or more packages. 470 There is one main package, which can list other packages as 471 dependencies, which can in turn list further dependencies. 472 There are multiple ways of specifying versions of packages,
3.1 Compiler Toolchain
509
510
The source TypeScript program is processed by the regular
511
TypeScript compiler to perform syntactic and semantic anal-
512
ysis, including type checking. This produces type-annotated
513
abstract syntax trees (ASTs) that are then checked for con-
514
structs outside of STS (eval, arguments, etc.). The AST
515
is then transformed into a custom intermediate represen-
516
tation (IR) with language constructs desugared to calls to
517
runtime functions. This IR is later transformed into one of
518
three forms:
519
1. continuation passing JavaScript for execution within 520
the browser (inside of a separate "simulator" IFrame) 521
2. ARM Thumb machine code, linked with pre-compiled 522
C++ runtime and executed on bare-metal hardware or 523
inside of an operating system
524
3. bytecode for a custom VM interpreter, meant for plat- 525
forms where where dynamic code loading/generation 526
is impossible (like XBox or iOS)
527
473 including built-in packages, file paths when operating from
474 command line, and URLs of GitHub repositories. There can
475 be only one version for each package (otherwise we would
476 likely get redefinition errors).
477
MakeCode editor builders will generally decide to include
478 a number of built-in packages, which ship with the editor.
479 These can be further extended with packages coming from
480 GitHub. The MakeCode web app has support for authoring
481 and publishing packages to GitHub. Because namespaces are
Both the ARM Thumb and the custom bytecode are gener- 528
ated in form of assembly code, and translated to machine 529
code by a custom assembler. In this section we focus on the 530
native 32-bit ARM Thumb target (though we compare the 531
performance of the VM, see Section 4.2).
532
The regular TypeScript compiler, the STS code generators, 533
assembler, and linker are all implemented in TypeScript and 534
run both in the web browser and on command line.
535
536
482 independent of files, it is easy for packages to extend existing
483 namespaces. Currently, STS does not enforce any discipline
484 here.
485
MakeCode comes with a number of packages that editor
486 builders can include (common packages). They provide sup-
487 port for various hardware features (pins, buttons, buzzer,
488 screen, etc.), as well as higher-level concepts like sprite-
489 handling game library. Some of these packages come in vari-
490 ants, sharing interface but with different implementations
3.2 Linking
537
The generated machine code is linked to a pre-compiled 538
C++ runtime. C++ compilation takes place in a cloud service, 539
with the resulting runtime cached both in the cloud content 540
delivery network, and in the browser (caching is based on a 541
strong hash of all the C++ sources, options etc.). Typically, 542
the C++ runtime does not change while the user is working 543
on their program, allowing for offline operation.5
544
545
491 (eg., drivers for different screens).
492
External (GitHub) packages typically provide support for
493 other hardware peripherals. Users typically do not use too
494 many external packages at once, so we feel the risk of name
5While it could be possible to compile the C++ code locally using Emscripten
546
or similar technologies, the compilation toolchain, header files, and libraries
547
would likely require tens of megabytes of download straining offline storage
548
in the browser.
549
495
5
550
................
................
In order to avoid copyright disputes, this page is only a partial summary.
To fulfill the demand for quickly locating and searching documents.
It is intelligent file search solution for home and business.
Related download
- typescript notes for professionals
- static typescript
- typescript handbook
- javascript check if object has property
- cognitive complexity sonarsource
- typescript delivery check list cork university press
- check variable of object for if statement sulok
- declare module typescript object
- electronic check echeck payment authorization form
- cognitive complexity
Related searches
- static equilibrium equation
- static equilibrium calculations formula
- typescript static methods
- typescript static functions
- typescript interface static member
- typescript class static property
- typescript static class function
- typescript static function
- typescript class static member
- typescript static variable
- typescript interface static method
- typescript static map