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.

Google Online Preview   Download

To fulfill the demand for quickly locating and searching documents.

It is intelligent file search solution for home and business.

Literature Lottery

Related searches