or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context-management.mdindex.mdio-filesystem.mdlanguage-execution.mdmonitoring-management.mdproxy-system.mdsecurity-access.mdvalue-interop.md

language-execution.mddocs/

0

# Language Execution and Source Parsing

1

2

The GraalVM Polyglot API provides comprehensive capabilities for executing and parsing code across multiple programming languages. This includes source code creation, evaluation, parsing, and language bindings management.

3

4

## Source Creation and Management

5

6

The Source class represents source code with language and metadata information, supporting various input formats and caching strategies.

7

8

### Source Factory Methods

9

10

```java { .api }

11

// Simple source creation

12

public static Source create(String language, CharSequence source);

13

14

// Builder pattern for advanced configuration

15

public static Source.Builder newBuilder(String language, CharSequence characters, String name);

16

public static Source.Builder newBuilder(String language, ByteSequence bytes, String name);

17

public static Source.Builder newBuilder(String language, File file);

18

public static Source.Builder newBuilder(String language, URL url);

19

public static Source.Builder newBuilder(String language, Reader source, String name);

20

```

21

22

**Basic Source Creation:**

23

24

```java

25

// Inline source code

26

Source jsSource = Source.create("js", "function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }");

27

28

// From file

29

Source pySource = Source.newBuilder("python", new File("script.py")).build();

30

31

// From URL with caching

32

Source webSource = Source.newBuilder("js", new URL("https://example.com/script.js"))

33

.cached(true)

34

.build();

35

```

36

37

### Source Builder Configuration

38

39

```java { .api }

40

public static final class Source.Builder {

41

// Content and encoding

42

public Source.Builder content(CharSequence characters);

43

public Source.Builder content(ByteSequence bytes);

44

public Source.Builder encoding(Charset encoding);

45

46

// Metadata

47

public Source.Builder name(String name);

48

public Source.Builder mimeType(String mimeType);

49

public Source.Builder uri(URI uri);

50

51

// Behavior configuration

52

public Source.Builder cached(boolean cached);

53

public Source.Builder interactive(boolean interactive);

54

public Source.Builder internal(boolean internal);

55

56

// Build the source

57

public Source build();

58

}

59

```

60

61

### Language and MIME Type Discovery

62

63

```java { .api }

64

// Language detection from file/URL

65

public static String findLanguage(File file);

66

public static String findLanguage(URL url);

67

public static String findLanguage(String mimeType);

68

69

// MIME type detection

70

public static String findMimeType(File file);

71

public static String findMimeType(URL url);

72

```

73

74

**Language Detection Example:**

75

76

```java

77

File jsFile = new File("script.js");

78

String language = Source.findLanguage(jsFile); // Returns "js"

79

String mimeType = Source.findMimeType(jsFile); // Returns "application/javascript"

80

81

// Create source with auto-detected language

82

Source source = Source.newBuilder(language, jsFile).build();

83

```

84

85

### Source Content Access

86

87

```java { .api }

88

public final class Source {

89

// Basic properties

90

public String getLanguage();

91

public String getName();

92

public String getPath();

93

public URL getURL();

94

public URI getURI();

95

public String getMimeType();

96

97

// Content access

98

public CharSequence getCharacters();

99

public CharSequence getCharacters(int lineNumber);

100

public ByteSequence getBytes();

101

public Reader getReader();

102

public InputStream getInputStream();

103

public int getLength();

104

105

// Source properties

106

public boolean isInteractive();

107

public boolean isInternal();

108

public boolean hasCharacters();

109

public boolean hasBytes();

110

111

// Line and column operations

112

public int getLineCount();

113

public int getLineNumber(int offset);

114

public int getColumnNumber(int offset);

115

}

116

```

117

118

## Code Evaluation

119

120

The Context class provides methods for evaluating source code with immediate execution and result retrieval.

121

122

### Evaluation Methods

123

124

```java { .api }

125

// Evaluate source objects

126

public Value eval(Source source);

127

128

// Evaluate inline code

129

public Value eval(String languageId, CharSequence source);

130

```

131

132

**Evaluation Examples:**

133

134

```java

135

Context context = Context.create("js", "python");

136

137

// JavaScript evaluation

138

Value jsResult = context.eval("js", "Math.PI * 2");

139

System.out.println(jsResult.asDouble()); // 6.283185307179586

140

141

// Python evaluation

142

Value pyResult = context.eval("python", "[x**2 for x in range(5)]");

143

System.out.println(pyResult.toString()); // [0, 1, 4, 9, 16]

144

145

// Source object evaluation

146

Source factorial = Source.create("js", """

147

function factorial(n) {

148

return n <= 1 ? 1 : n * factorial(n-1);

149

}

150

factorial(5);

151

""");

152

Value factResult = context.eval(factorial);

153

System.out.println(factResult.asInt()); // 120

154

```

155

156

### Multi-Language Evaluation

157

158

```java

159

Context context = Context.create("js", "python", "ruby");

160

161

// JavaScript sets up data

162

context.eval("js", "var shared = { message: 'Hello from JavaScript', count: 42 };");

163

164

// Python accesses and modifies

165

context.eval("python", """

166

import polyglot

167

shared = polyglot.eval(language="js", string="shared")

168

shared.message = "Modified by Python"

169

shared.count = shared.count * 2

170

""");

171

172

// Ruby reads the result

173

Value rubyResult = context.eval("ruby", """

174

shared = Polyglot.eval("js", "shared")

175

"#{shared[:message]} - Count: #{shared[:count]}"

176

""");

177

178

System.out.println(rubyResult.asString()); // "Modified by Python - Count: 84"

179

```

180

181

## Code Parsing

182

183

Parsing allows you to compile source code without immediate execution, enabling syntax validation and AST preparation.

184

185

### Parsing Methods

186

187

```java { .api }

188

// Parse source objects

189

public Value parse(Source source);

190

191

// Parse inline code

192

public Value parse(String languageId, CharSequence source);

193

```

194

195

**Parsing Examples:**

196

197

```java

198

Context context = Context.create("js");

199

200

// Parse without execution

201

Source jsFunction = Source.create("js", "function greet(name) { return 'Hello, ' + name; }");

202

Value parsed = context.parse(jsFunction);

203

204

// The function is now compiled but not executed

205

// Execute later with different arguments

206

Value greeting1 = context.eval("js", "greet('Alice')");

207

Value greeting2 = context.eval("js", "greet('Bob')");

208

```

209

210

### Parse vs. Eval

211

212

```java

213

Context context = Context.create("js");

214

215

// Parsing: Compiles but doesn't execute

216

Value parsed = context.parse("js", "console.log('This will not print during parsing')");

217

// No output - just compilation

218

219

// Evaluation: Compiles and executes

220

Value evaluated = context.eval("js", "console.log('This will print during evaluation')");

221

// Output: "This will print during evaluation"

222

223

// Execute the previously parsed code

224

context.eval("js", "console.log('Now executing parsed code')");

225

// Output: "This will not print during parsing"

226

```

227

228

## Language Bindings

229

230

Bindings provide a way to share values between the host (Java) and guest languages, as well as between different guest languages.

231

232

### Language-Specific Bindings

233

234

```java { .api }

235

// Get bindings for a specific language

236

public Value getBindings(String languageId);

237

238

// Get polyglot bindings (shared across languages)

239

public Value getPolyglotBindings();

240

```

241

242

### Bindings Operations

243

244

Language bindings behave like a Map-like object where you can store and retrieve values by name.

245

246

```java

247

Context context = Context.create("js", "python");

248

249

// Get JavaScript bindings

250

Value jsBindings = context.getBindings("js");

251

252

// Add host objects to JavaScript

253

jsBindings.putMember("javaList", Arrays.asList(1, 2, 3, 4, 5));

254

jsBindings.putMember("javaMap", Map.of("key1", "value1", "key2", "value2"));

255

256

// JavaScript can now access these objects

257

context.eval("js", """

258

console.log('Java list length:', javaList.length);

259

console.log('Java map key1:', javaMap.get('key1'));

260

""");

261

262

// Set values from JavaScript

263

context.eval("js", "var jsResult = javaList.reduce((sum, x) => sum + x, 0);");

264

265

// Access JavaScript values from Java

266

Value jsResult = jsBindings.getMember("jsResult");

267

System.out.println("Sum calculated in JS: " + jsResult.asInt()); // 15

268

```

269

270

### Polyglot Bindings

271

272

Polyglot bindings are shared across all languages in a context:

273

274

```java

275

Context context = Context.create("js", "python");

276

277

// Get shared polyglot bindings

278

Value polyglotBindings = context.getPolyglotBindings();

279

280

// Add shared data

281

polyglotBindings.putMember("sharedCounter", 0);

282

polyglotBindings.putMember("sharedConfig", Map.of("debug", true, "version", "1.0"));

283

284

// JavaScript increments counter

285

context.eval("js", """

286

Polyglot.import('sharedCounter');

287

var currentCount = Polyglot.import('sharedCounter');

288

Polyglot.export('sharedCounter', currentCount + 1);

289

""");

290

291

// Python also increments counter

292

context.eval("python", """

293

import polyglot

294

current = polyglot.import_value('sharedCounter')

295

polyglot.export_value('sharedCounter', current + 10)

296

""");

297

298

// Read final value

299

Value finalCount = polyglotBindings.getMember("sharedCounter");

300

System.out.println("Final counter: " + finalCount.asInt()); // 11

301

```

302

303

## Host Value Conversion

304

305

The Context provides methods to convert Java objects to polyglot values that can be used by guest languages.

306

307

### Value Conversion

308

309

```java { .api }

310

// Convert host objects to polyglot values

311

public Value asValue(Object hostValue);

312

```

313

314

**Conversion Examples:**

315

316

```java

317

Context context = Context.create("js");

318

319

// Convert various Java types

320

Value stringValue = context.asValue("Hello World");

321

Value intValue = context.asValue(42);

322

Value listValue = context.asValue(Arrays.asList(1, 2, 3));

323

Value mapValue = context.asValue(Map.of("name", "Alice", "age", 30));

324

325

// Custom objects (with HostAccess configuration)

326

public class Person {

327

@HostAccess.Export public String name;

328

@HostAccess.Export public int age;

329

330

@HostAccess.Export

331

public String greet() {

332

return "Hello, I'm " + name;

333

}

334

}

335

336

Context restrictedContext = Context.newBuilder("js")

337

.allowHostAccess(HostAccess.EXPLICIT)

338

.build();

339

340

Person person = new Person();

341

person.name = "Alice";

342

person.age = 30;

343

344

Value personValue = restrictedContext.asValue(person);

345

346

// Make available to JavaScript

347

Value jsBindings = restrictedContext.getBindings("js");

348

jsBindings.putMember("person", personValue);

349

350

restrictedContext.eval("js", """

351

console.log(person.name); // "Alice"

352

console.log(person.age); // 30

353

console.log(person.greet()); // "Hello, I'm Alice"

354

""");

355

```

356

357

## Language Initialization

358

359

Contexts support lazy initialization of languages, improving startup performance when not all languages are immediately needed.

360

361

### Language Initialization Control

362

363

```java { .api }

364

// Explicitly initialize a language

365

public boolean initialize(String languageId);

366

```

367

368

**Initialization Example:**

369

370

```java

371

Context context = Context.create("js", "python", "ruby");

372

373

// Initially, no languages are initialized

374

// First evaluation triggers initialization

375

long startTime = System.currentTimeMillis();

376

context.eval("js", "1 + 1"); // JavaScript gets initialized here

377

long jsInitTime = System.currentTimeMillis() - startTime;

378

379

// Subsequent evaluations are faster

380

startTime = System.currentTimeMillis();

381

context.eval("js", "2 + 2"); // No initialization needed

382

long jsExecTime = System.currentTimeMillis() - startTime;

383

384

// Pre-initialize Python for faster first execution

385

context.initialize("python");

386

Value pyResult = context.eval("python", "len([1, 2, 3, 4, 5])");

387

```

388

389

## Error Handling

390

391

Language execution can produce various types of errors that should be handled appropriately.

392

393

### Exception Types

394

395

```java

396

Context context = Context.create("js");

397

398

try {

399

// Syntax error

400

context.eval("js", "function malformed { missing parentheses }");

401

} catch (PolyglotException e) {

402

if (e.isSyntaxError()) {

403

System.out.println("Syntax error: " + e.getMessage());

404

SourceSection location = e.getSourceLocation();

405

if (location != null) {

406

System.out.printf("At line %d, column %d%n",

407

location.getStartLine(), location.getStartColumn());

408

}

409

}

410

}

411

412

try {

413

// Runtime error

414

context.eval("js", "nonExistentFunction()");

415

} catch (PolyglotException e) {

416

if (e.isGuestException()) {

417

System.out.println("Runtime error in guest language: " + e.getMessage());

418

Value guestObject = e.getGuestObject();

419

// Handle guest exception object

420

}

421

}

422

```

423

424

## Source Location Information

425

426

Source sections provide detailed location information for debugging and error reporting.

427

428

### SourceSection Details

429

430

```java { .api }

431

public final class SourceSection {

432

public Source getSource();

433

public int getStartLine();

434

public int getEndLine();

435

public int getStartColumn();

436

public int getEndColumn();

437

public int getCharIndex();

438

public int getCharLength();

439

public int getCharEndIndex();

440

public boolean isAvailable();

441

public boolean hasLines();

442

public boolean hasColumns();

443

public boolean hasCharIndex();

444

public CharSequence getCharacters();

445

}

446

```

447

448

**Source Location Example:**

449

450

```java

451

Source source = Source.newBuilder("js", """

452

function calculate(x, y) {

453

return x / y; // Division by zero potential

454

}

455

calculate(10, 0);

456

""", "calculator.js").build();

457

458

Context context = Context.create("js");

459

460

try {

461

context.eval(source);

462

} catch (PolyglotException e) {

463

SourceSection location = e.getSourceLocation();

464

if (location != null) {

465

System.out.printf("Error in %s:%d:%d-%d:%d%n",

466

location.getSource().getName(),

467

location.getStartLine(), location.getStartColumn(),

468

location.getEndLine(), location.getEndColumn());

469

System.out.printf("Code: %s%n", location.getCharacters());

470

}

471

}

472

```

473

474

## Performance Considerations

475

476

### Source Caching

477

478

```java

479

// Enable source caching for repeated evaluation

480

Source cachedSource = Source.newBuilder("js", new File("frequent-script.js"))

481

.cached(true)

482

.build();

483

484

// Multiple contexts can share the cached source

485

Context context1 = Context.create("js");

486

Context context2 = Context.create("js");

487

488

context1.eval(cachedSource); // Parsed and cached

489

context2.eval(cachedSource); // Uses cached parse result

490

```

491

492

### Parsing vs. Evaluation

493

494

```java

495

Context context = Context.create("js");

496

497

// For repeated execution, parse once and reference

498

Source template = Source.create("js", "function process(data) { /* complex logic */ }");

499

context.parse(template); // One-time compilation

500

501

// Then evaluate with different data

502

for (Object data : dataSet) {

503

Value bindings = context.getBindings("js");

504

bindings.putMember("currentData", data);

505

context.eval("js", "process(currentData)");

506

}

507

```