interactive 1.0.0 copy "interactive: ^1.0.0" to clipboard
interactive: ^1.0.0 copied to clipboard

REPL (interactive shelL) for Dart, supporting 3rd party packages, hot reload, and full grammar

dart_interactive #

🚀 Features #

  • Use any third-party package freely
  • Auto hot-reload code anywhere, preserving state
  • Supports full grammar in REPL

In short: A full-featured REPL (interactive shell). For more details, please see section below.

📚 Demo #

TODO

🎼 Getting started #

Install (just standard procedure of installing global dart packages):

dart pub global activate interactive

Use (just a normal binary):

interactive

And play with it :)

Feature details #

Expressions #

>>> a = 'Hello'; b = ' world!'; 
>>> '$a, $b'                   
Hello,  world!

Statements #

>>> print(a)
Hello

(All methods, not only print)

Functions #

Define and redefine

>>> String f() => 'old';
>>> f()
old
>>> String f() => 'new';
>>> f()
new

Use local and global variables

>>> a = 10;
>>> int f() { int b = 20; a++; b++; return a+b; }
>>> f() 
32
>>> f()
33

Classes #

Define and redefine, preserving states

>>> class C { int a = 10; int f() => a * 2; }
>>> c = C(); print(c.f());
20
>>> class C { int a = 1000; int f() => a * 3; }
>>> c.f()
30

Remark: This follows the Dart hot reload semantics.

Extends and implements

>>> class A { int f() => 10; } class B extends A { int f() => 20; }
>>> A().f() + B().f()
30
>>> class B implements A { int f() => 30; }
>>> A().f() + B().f()
40

Use local variables, fields, and global variables

>>> a = 10;
>>> class C { int b = 20; int f() { int c = 30; a++; b++; c++; return a+b+c; } }
>>> c = C(); print(c.f()); print(c.f());
63
65

Add libraries as dependency #

Use !dart pub add package_name, just like what is done in Python (Jupyter/IPython).

>>> join('directory', 'file.txt')
(...error, since have not added that dependency...)
>>> !dart pub add path
Resolving dependencies...

+ path 1.8.2

Changed 1 dependency!

>>> join('directory', 'file.txt')
(...error, since have imported it...)
>>> import 'package:path/path.dart';
>>> join('directory', 'file.txt')   
directory/file.txt

Imports #

Built-in package

>>> Random().nextInt(100)
(some error outputs here, because it is not imported)
>>> import "dart:math";
>>> Random().nextInt(100)
9

Third party package

Note: If it has not been added to dependency, please follow instructions above and use !dart pub add path to add it.

>>> join('directory', 'file.txt')
(...error, since have imported it...)
>>> import 'package:path/path.dart';
>>> join('directory', 'file.txt')   
directory/file.txt

Multiple in one go #

>>> int g() => 42; class C { int a = 10; int f() => a * 2; }
>>> C().f() + g()
62

Multi line if not ended #

(The ..., instead of >>>, appears in the two lines, because the package detects it is not finished.)

>>> class C {
...   int a = 10;
... }
>>> 

Run commands #

Use prefix !.

>>> !whoami
tom
>>> !date
2022-10-22 ...outputs...

Implementation #

General:

  • Create a blank package and an isolate as execution workspace
  • Extract imports/classes/functions/etc using analyzer, with replacing when it has the same name, and synthesize a dart file - thus supports rich Dart feature
  • Trigger Dart's hot-reload after the dart file is updated
  • Use analyzer to distinguish expressions/statements/compilation-units and do corresponding transformation
  • The only thing to let Dart VM service to evaluate is generatedMethod(), and do not evaluate anything more
  • Adding dependencies is as simple as running standard shell command

As for "global" variables:

  • Indeed implemented by a field variable
  • Statements: Make it inside extension on dynamic { Object? generatedMethod() { ...the statements... } } to access it seamlessly
  • Functions: Convert functions to extension methods on dynamic to access it seamlessly
  • Classes: Synthesize getters/setters in classes, and delegate to the field variables, whenever there is a potential access to global variable to access it seamlessly

TODO more implementation discussions if people are interested (above is so brief)

✨ Contributors #

All Contributors

Thanks goes to these wonderful people (emoji key):

fzyzcjy
fzyzcjy

💻 📖 🤔
Vyacheslav Egorov
Vyacheslav Egorov

🤔
Andreas Kirsch
Andreas Kirsch

🤔
Maksim Lin
Maksim Lin

🤔

More specifically, thanks for all these contributions:

30
likes
0
pub points
11%
popularity

Publisher

verified publishercjycode.com

REPL (interactive shelL) for Dart, supporting 3rd party packages, hot reload, and full grammar

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

analyzer, args, cli_repl, collection, logging, path, vm_service

More

Packages that depend on interactive