{"id":13549693,"url":"https://github.com/ethanblake4/dart_eval","last_synced_at":"2025-04-08T00:37:55.578Z","repository":{"id":37985489,"uuid":"356779190","full_name":"ethanblake4/dart_eval","owner":"ethanblake4","description":"Extensible Dart interpreter for Dart with full interop","archived":false,"fork":false,"pushed_at":"2024-11-25T18:42:55.000Z","size":4121,"stargazers_count":351,"open_issues_count":53,"forks_count":43,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-31T23:34:45.604Z","etag":null,"topics":["codepush","compiler","dart","flutter","interpreter"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/dart_eval","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ethanblake4.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-11T05:53:27.000Z","updated_at":"2025-03-09T19:44:28.000Z","dependencies_parsed_at":"2023-01-30T21:30:47.482Z","dependency_job_id":"780c9815-7ca7-4841-b2d6-d10181983249","html_url":"https://github.com/ethanblake4/dart_eval","commit_stats":{"total_commits":289,"total_committers":13,"mean_commits":22.23076923076923,"dds":"0.31833910034602075","last_synced_commit":"b06ed0de64bf1c494f07497fec1e4e8a59f02854"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanblake4%2Fdart_eval","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanblake4%2Fdart_eval/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanblake4%2Fdart_eval/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanblake4%2Fdart_eval/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ethanblake4","download_url":"https://codeload.github.com/ethanblake4/dart_eval/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247755560,"owners_count":20990620,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codepush","compiler","dart","flutter","interpreter"],"created_at":"2024-08-01T12:01:24.507Z","updated_at":"2025-04-08T00:37:55.530Z","avatar_url":"https://github.com/ethanblake4.png","language":"Dart","readme":"[![Build status](https://img.shields.io/github/actions/workflow/status/ethanblake4/dart_eval/dart.yml?branch=master)](https://github.com/ethanblake4/dart_eval/actions/workflows/dart.yml)\n[![License: BSD-3](https://img.shields.io/badge/license-BSD3-purple.svg)](https://opensource.org/licenses/BSD-3-Clause)\n[![Web example](https://img.shields.io/badge/web-example-blue.svg)](https://ethanblake.xyz/evalpad)\n[![Star on Github](https://img.shields.io/github/stars/ethanblake4/dart_eval?logo=github\u0026colorB=orange\u0026label=stars)](https://github.com/ethanblake4/dart_eval)\n\n`dart_eval` is an extensible bytecode compiler and interpreter for the Dart language, \nwritten in Dart, enabling dynamic execution and codepush for Flutter and Dart AOT.\n\n| dart_eval    | [![pub package](https://img.shields.io/pub/v/dart_eval.svg?label=dart_eval\u0026color=teal)](https://pub.dev/packages/dart_eval)          |\n| ------------ | ------------------------------------------------------------------------------------------------------------------------------------ |\n| flutter_eval | [![pub package](https://img.shields.io/pub/v/flutter_eval.svg?label=flutter_eval\u0026color=blue)](https://pub.dev/packages/flutter_eval) |\n| eval_annotation | [![pub package](https://img.shields.io/pub/v/eval_annotation.svg?label=eval_annotation\u0026color=orange)](https://pub.dev/packages/eval_annotation) |\n\nThe primary aspect of `dart_eval`'s goal is to be interoperable with real \nDart code. Classes created in 'real Dart' can be used inside the interpreter \nwith a [wrapper](#wrapper-interop), and classes created in the interpreter \ncan be used outside it by creating an interface and [bridge class](#bridge-interop).\n\ndart_eval's compiler is powered under the hood by the Dart \n[analyzer](https://pub.dev/packages/analyzer), so it achieves 100% correct and \nup-to-date parsing. While compilation and execution aren't quite there yet, dart_eval\nhas over 200 tests that are run in CI to ensure correctness.\n\nCurrently dart_eval implements a majority of the Dart spec, but there \nare still missing features like generators, Sets and extension methods.\nIn addition, parts of the standard library haven't been implemented. See the\n[language feature support table](#language-feature-support-table) for details.\n\n## Usage\n\n\u003e **Note**: See the README for [flutter_eval](https://pub.dev/packages/flutter_eval) for\ninformation on setting up Flutter code push.\n\nA basic usage example of the `eval` method, which is a simple shorthand to\nexecute Dart code at runtime:\n\n```dart\nimport 'package:dart_eval/dart_eval.dart';\n\nvoid main() {\n  print(eval('2 + 2')); // -\u003e 4\n  \n  final program = r'''\n      class Cat {\n        Cat(this.name);\n        final String name;\n        String speak() =\u003e \"I'm $name!\";\n      }\n      String main() {\n        final cat = Cat('Fluffy');\n        return cat.speak();\n      }\n  ''';\n  \n  print(eval(program, function: 'main')); // prints 'I'm Fluffy!'\n}\n```\n\n## Passing arguments\nIn most cases, you should wrap arguments you pass to dart_eval in `$Value`\nwrappers, such as `$String` or `$Map`. These 'boxed types' have information \nabout what they are and how to modify them, and you can access their underlying\nvalue with the `$value` property. However, ints, doubles, bools, \nand Lists are treated as primitives and should be passed without wrapping\nwhen their exact type is specified in the function signature:\n\n```dart\nfinal program = '''\n  int main(int count, String str) {\n    return count + str.length;\n  }\n''';\n\nprint(eval(program, function: 'main', args: [1, $String('Hi!')])); // -\u003e 4\n```\n\nWhen calling a function or constructor externally, you must specify all arguments - even optional and named ones - in order, using null to indicate the absence of an argument (whereas $null() indicates a null value).\n\n## Passing callbacks\nYou can pass callbacks as arguments to dart_eval using `$Closure`:\n  \n```dart\nimport 'package:dart_eval/dart_eval.dart';\nimport 'package:dart_eval/dart_eval_bridge.dart';\n\nvoid main() {\n  final program = '''\n    void main(Function callback) {\n      callback('Hello');\n    }\n  ''';\n\n  eval(program, function: 'main', args: [\n    $Closure((runtime, target, args) {\n      print(args[0]!.$value + '!');\n      return null;\n    })\n  ]); // -\u003e prints 'Hello!'\n}\n```\n\n## Advanced usage\nFor more advanced usage, you can use the Compiler and Runtime classes directly,\nwhich will allow you to use multiple 'files' and customize how the program is run:\n\n```dart\nimport 'package:dart_eval/dart_eval.dart';\n\nvoid main() {\n  final compiler = Compiler();\n  \n  final program = compiler.compile({'my_package': {\n    'main.dart': '''\n      import 'package:my_package/finder.dart';\n      void main() {\n        final parentheses = findParentheses('Hello (world)');\n        if (parentheses.isNotEmpty) print(parentheses); \n      }\n    ''',\n    'finder.dart': r'''\n      List\u003cint\u003e findParentheses(string) {\n        final regex = RegExp(r'\\((.*?)\\)');\n        final matches = regex.allMatches(string);\n        return matches.map((match) =\u003e match.start).toList();\n      }\n    '''\n  }});\n  \n  final runtime = Runtime.ofProgram(program);\n  print(runtime.executeLib(\n    'package:my_package/main.dart', 'main')); // prints '[6]'\n}\n```\n\n## Entrypoints and tree-shaking\n\ndart_eval uses tree-shaking to avoid compiling unused code. By default, \nany file named `main.dart` or that contains [runtime overrides](#runtime-overrides) will be treated as an entrypoint and guaranteed to be compiled in its entirety. To add additional entrypoints, append URIs to the\n`Compiler.entrypoints` array:\n\n```dart\nfinal compiler = Compiler();\ncompiler.entrypoints.add('package:my_package/some_file.dart');\ncompiler.compile(...);\n```\n\n## Compiling to a file\n\nIf possible, it's recommended to pre-compile your Dart code to EVC bytecode,\nto avoid runtime compilation overhead. (This is still runtime code execution, it's\njust executing a more efficient code format.) Multiple files will be compiled to a\nsingle bytecode block.\n\n```dart\nimport 'dart:io';\nimport 'package:dart_eval/dart_eval.dart';\n\nvoid main() {\n  final compiler = Compiler();\n  \n  final program = compiler.compile({'my_package': {\n    'main.dart': '''\n      int main() {\n        var count = 0;\n        for (var i = 0; i \u003c 1000; i++) {\n          count += i;\n        }\n        return count;\n      }\n    '''\n  }});\n  \n  final bytecode = program.write();\n  \n  final file = File('program.evc');\n  file.writeAsBytesSync(bytecode);\n}\n```\n\nYou can then load and execute the program later:\n\n```dart\nimport 'dart:io';\nimport 'package:dart_eval/dart_eval.dart';\n\nvoid main() {\n  final file = File('program.evc');\n  final bytecode = file\n      .readAsBytesSync()\n      .buffer\n      .asByteData();\n  \n  final runtime = Runtime(bytecode);\n  print(runtime.executeLib(\n    'package:my_package/main.dart', 'main')); // prints '499500'\n}\n```\n\n## Using the CLI\nThe dart_eval CLI allows you to compile existing Dart projects to EVC bytecode,\nas well as run and inspect EVC bytecode files.\n\nTo enable the CLI globally, run:\n\n`dart pub global activate dart_eval`\n\n### Compiling a project\n\nThe CLI supports compiling standard Dart projects. To compile a project, run:\n\n```bash\ncd my_project\ndart_eval compile -o program.evc\n```\n\nThis will generate an EVC file in the current directory called `program.evc`.\ndart_eval will attempt to compile Pub packages, but it's recommended to\navoid them as they may use features that dart_eval doesn't support yet.\n\nThe compiler also supports compiling with JSON-encoded bridge bindings. To add\nthese, create a folder in your project root called `.dart_eval`, add a\n`bindings` subfolder, and place JSON binding files there. The compiler will\nautomatically load these bindings and make them available to your project.\n\n### Running a program\n\nTo run the generated EVC file, use:\n\n`dart_eval run program.evc -p package:my_package/main.dart -f main`\n\nNote that the run command does *not* support bindings, so any file compiled\nwith bindings will need to be run in a specialized runner that includes the\nnecessary runtime bindings.\n\n### Inspecting an EVC file\n\nYou can dump the op codes of an EVC file using:\n\n`dart_eval dump program.evc`\n\n## Return values\n\nLike with arguments, dart_eval will return a `$Value` wrapper for most values\nexcept ints, doubles, bools, and Lists. If you don't like this inconsistency,\nspecifying a function's return value as `dynamic` will force dart_eval to\nalways box the return value in a `$Value` wrapper.\n\n\u003e Note that this does not apply to the `eval()` method, which automatically\nunboxes all return values for convenience.\n\n## Security and permissions\n\ndart_eval is designed to be secure. The dart_eval runtime functions like a virtual\nmachine, effectively sandboxing the code it executes. By default, the runtime will\nnot allow running programs to access the file system, network, or other system \nresources, but these permissions can be enabled on a granular basis using \n`runtime.grant`:\n\n```dart\nfinal runtime = Runtime(bytecode);\n\n// Allow full access to the file system\nruntime.grant(FilesystemPermission.any);\n\n// Allow access to a specific network domain\nruntime.grant(NetworkPermission.url('example.com'));\n\n// Allow access to a specific network resource\nruntime.grant(NetworkPermission.url('https://dart.dev/api/users.json'));\n\n// Using the eval() method\neval(source, permissions: [\n  NetworkPermission.any,\n  FilesystemReadPermission.directory('/home/user/mydata'), \n  ProcessRunPermission(RegExp(r'^ls$'))\n]);\n```\n\nPermissions can also be revoked using `runtime.revoke`.\n\nWhen writing bindings that access sensitive resources, you can check whether a \npermission is enabled using `runtime.checkPermission`, or assert using\n`runtime.assertPermission`. Out of the box, dart_eval includes the FilesystemPermission, \nNetworkPermission, and Process(Run/Kill)Permission classes \n('filesystem', 'network', and 'process' domains, respectively)\nas well as read/write only variations of FilesystemPermission, but \nyou can also create your own custom permissions by implementing the Permission\ninterface.\n\n## Interop\n\nInterop is a general term for methods in which we can access, use, and modify data\nfrom dart_eval in Dart. Enabling this access is a high priority for dart_eval.\n\nThere are three main levels of interop:\n* Value interop\n* Wrapper interop\n* Bridge interop\n\n### Value interop\n\nValue interop happens automatically whenever dart_eval is working\nwith an object backed by a real Dart value. (Therefore, an int and a string\nare value interop enabled, but a class created inside Eval isn't.)\nTo access the backing object of a `$Value`, use its `$value` property. If the\nvalue is a collection like a Map or a List, you can use its `$reified` property\nto also unwrap the values it contains.\n\n### Wrapper interop\n\nUsing a wrapper enables the Eval environment to access the functions and fields on\na class created outside Eval. It's much more powerful than value interop, and\nmore performant than bridge interop, making it a great choice for certain use \ncases. To use wrapper interop, create a class that implements `$Instance`, and\na compile-time class definition. Then, override `$getProperty`, `$setProperty`\nand `$getRuntimeType` to enable the Eval environment to access the class's\nproperties and methods:\n\n```dart\nimport 'package:dart_eval/dart_eval.dart';\nimport 'package:dart_eval/dart_eval_bridge.dart';\nimport 'package:dart_eval/dart_eval_extensions.dart';\n\n/// An example class we want to wrap\nclass Book {\n  Book(this.pages);\n  final List\u003cString\u003e pages;\n  \n  String getPage(int index) =\u003e pages[index];\n}\n\n/// This is our wrapper class\nclass $Book implements $Instance {\n  /// Create a type specification for the dart_eval compiler\n  static final $type = BridgeTypeSpec('package:hello/book.dart', 'Book').ref;\n\n  /// Create a class declaration for the dart_eval compiler\n  static final $declaration = BridgeClassDef(BridgeClassType($type),\n    constructors: {\n      // Define the default constructor with an empty string\n      '': BridgeFunctionDef(returns: $type.annotate, params: [\n        'pages'.param(CoreTypes.list.refWith([CoreTypes.string.ref]).annotate)\n      ]).asConstructor\n    },\n    methods: {\n      'getPage': BridgeFunctionDef(\n        returns: CoreTypes.string.ref.annotate,\n        params: ['index'.param(CoreTypes.int.ref.annotate)],\n      ).asMethod,\n    }, wrap: true);\n\n  /// Override $value and $reified to return the value\n  @override\n  final Book $value;\n\n  @override\n  get $reified =\u003e $value;\n  \n  /// Create a constructor that wraps the Book class\n  $Book.wrap(this.$value);\n  \n  static $Value? $new(\n    Runtime runtime, $Value? target, List\u003c$Value?\u003e args) {\n    return $Book.wrap(Book(args[0]!.$value));\n  }\n\n  /// Create a wrapper for property and method getters\n  @override\n  $Value? $getProperty(Runtime runtime, String identifier) {\n    if (identifier == 'getPage') {\n      return $Function((_, target, args) {\n        return $String($value.getPage(args[0]!.$value));\n      });\n    }\n    return $Object(this).$getProperty(runtime, identifier);\n  }\n\n  /// Create a wrapper for property setters\n  @override\n  void $setProperty(Runtime runtime, String identifier, $Value value) {\n    return $Object(this).$setProperty(runtime, identifier, value);\n  }\n\n  /// Allow runtime type lookup\n  @override\n  int $getRuntimeType(Runtime runtime) =\u003e runtime.lookupType($type.spec!);\n}\n\n/// Now we can use it in dart_eval!\nvoid main() {\n  final compiler = Compiler();\n  compiler.defineBridgeClass($Book.$declaration);\n  \n  final program = compiler.compile({'hello' : { \n    'main.dart': '''\n      import 'book.dart';\n      void main() {\n        final book = Book(['Hello world!', 'Hello again!']);\n        print(book.getPage(1));\n      }\n    '''\n  }});\n\n  final runtime = Runtime.ofProgram(program);\n  // Register static methods and constructors with the runtime\n  runtime.registerBridgeFunc('package:hello/book.dart', 'Book.', $Book.$new);\n\n  runtime.executeLib('package:hello/main.dart', 'main'); // -\u003e 'Hello again!'\n}\n```\n\nFor more information,\nsee the [wrapper interop wiki page](https://github.com/ethanblake4/dart_eval/wiki/Wrappers).\n\n#### (Experimental) Binding generation for wrappers\nAs of v0.7.1 the dart_eval CLI includes an experimental wrapper binding generator. \nIt can be invoked in a project using `dart_eval bind`, and will generate bindings\nfor all classes annotated with the @Bind annotation from the eval_annotation package.\nYou can also pass the '--all' flag to generate bindings for all classes in the project.\nNote that generated bindings don't support every edge case, and may require manual\nadjustment.\n\nBinding generation cannot currently create JSON bindings directly, but you can\nuse the generated Dart bindings to create JSON bindings using a `BridgeSerializer`.\n\n### Bridge interop\n\nBridge interop enables the most functionality: Not only can dart_eval access the fields\nof an object, but it can also be extended, allowing you to create subclasses within Eval\nand use them outside of dart_eval. For example, this can be used to create custom\nFlutter widgets that can be dynamically updated at runtime. Bridge interop is also in \nsome ways simpler than creating a wrapper, but it comes at a performance cost, so should\nbe avoided in performance-sensitive situations. To use bridge interop, extend the original\nclass and mixin `$Bridge`:\n\n```dart\n// ** See previous example for the original class and imports **\n\n/// This is our bridge class\nclass $Book$bridge extends Book with $Bridge\u003cBook\u003e {\n  static final $type = ...; // See previous example\n  static final $declaration = ...; // Previous example, but use bridge: true instead of wrap\n\n  /// Recreate the original constructor\n  $Book$bridge(super.pages);\n\n  static $Value? $new(\n    Runtime runtime, $Value? target, List\u003c$Value?\u003e args) {\n    return $Book$bridge((args[0]!.$reified as List).cast());\n  }\n\n  @override\n  $Value? $bridgeGet(String identifier) {\n    if (identifier == 'getPage') {\n      return $Function((_, target, args) {\n        return $String(getPage(args[0]!.$value));\n      });\n    } \n    throw UnimplementedError('Unknown property $identifier');\n  }\n\n  @override\n  $Value? $bridgeSet(String identifier) =\u003e \n    throw UnimplementedError('Unknown property $identifier');\n\n  /// Override the original class' properties and methods\n  @override\n  String getPage(int index) =\u003e $_invoke('getPage', [$int(index)]);\n\n  @override\n  List\u003cString\u003e get pages =\u003e $_get('pages');\n}\n\nvoid main() {\n  final compiler = Compiler();\n  compiler.defineBridgeClass($Book$bridge.$declaration);\n  \n  final program = compiler.compile({'hello' : { \n    'main.dart': '''\n      import 'book.dart';\n      class MyBook extends Book {\n        MyBook(List\u003cString\u003e pages) : super(pages);\n        String getPage(int index) =\u003e 'Hello world!';\n      }\n\n      Book main() {\n        final book = MyBook(['Hello world!', 'Hello again!']);\n        return book;\n      }\n    '''\n  }});\n\n  final runtime = Runtime.ofProgram(program);\n  runtime.registerBridgeFunc(\n    'package:hello/book.dart', 'Book.', $Book$bridge.$new, bridge: true);\n\n  // Now we can use the new book class outside dart_eval!\n  final book = runtime.executeLib('package:hello/main.dart', 'main') \n    as Book;\n  print(book.getPage(1)); // -\u003e 'Hello world!'\n}\n```\n\nAn example featuring both bridge and wrapper interop is available in the \n`example` directory. For more information, see the \n[wiki page on bridge classes](https://github.com/ethanblake4/dart_eval/wiki/Bridge-classes).\n\n## Plugins\n\nTo configure interop for compilation and runtime, it's recommended to create an\n`EvalPlugin` which enables reuse of Compiler instances. Basic example:\n  \n```dart\nclass MyAppPlugin implements EvalPlugin {\n  @override\n  String get identifier =\u003e 'package:myapp';\n\n  @override\n  void configureForCompile(BridgeDeclarationRegistry registry) {\n    registry.defineBridgeTopLevelFunction(BridgeFunctionDeclaration(\n      'package:myapp/functions.dart',\n      'loadData',\n      BridgeFunctionDef(\n          returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object)), params: [])\n    ));\n    registry.defineBridgeClass($CoolWidget.$declaration);\n  }\n\n  @override\n  void configureForRuntime(Runtime runtime) {\n    runtime.registerBridgeFunc('package:myapp/functions.dart', 'loadData', \n        (runtime, target, args) =\u003e $Object(loadData()));\n    runtime.registerBridgeFunc('package:myapp/classes.dart', 'CoolWidget.', $CoolWidget.$new);\n  }\n}\n```\n\nYou can then use this plugin with `Compiler.addPlugin` and `Runtime.addPlugin`.\n\n## Runtime overrides\n\ndart_eval includes a runtime overrides system that allows you to dynamically \nswap in new implementations of functions and constructors at runtime.\nTo use it, add a null-coalescing call to the `runtimeOverride()` method\nat every spot you want to be able to swap:\n\n```dart\nvoid main() {\n  // Give the override a unique ID\n  final result = runtimeOverride('#myFunction') ?? myFunction();\n  print(result);\n}\n\nString myFunction() =\u003e 'Original version of string';\n```\n\nNote that in some cases you may have to cast the return value of `runtimeOverride`\nas dart_eval is unable to specify generic parameters to the Dart type system.\n\nNext, mark a function in the eval code with the @RuntimeOverride annotation:\n\n```dart\n@RuntimeOverride('#myFunction')\nString myFunction() =\u003e 'Updated version of string'\n```\n\nFinally, follow the normal instructions to compile and run the program, but\ncall `loadGlobalOverrides` on the Runtime.\nThis will set the runtime as the single global runtime for the program, and \nload its overrides to be accessible by hot wrappers.\n\nWhen the program is run, the runtime will automatically replace the\nfunction call with the new implementation.\n\nOverrides can also be versioned, allowing you to roll out updates to a function\nimmediately using dart_eval and revert to a new native implementation after\nan official update is released. To version an override, simply add a semver\nversion constraint to the `@RuntimeOverride` annotation:\n\n```dart\n@RuntimeOverride('#login_page_get_data', version: '\u003c1.4.0')\n```\n\nWhen running the program, specify its current version by setting the value of\nthe `runtimeOverrideVersion` global property:\n\n```dart\nruntimeOverrideVersion = Version.parse('1.3.0');\n```\n\nNow, when the program is run, the runtime will automatically replace the instantiation\nonly if the app version is less than 1.4.0.\n\n## Contributing\n\nSee [Contributing](https://github.com/ethanblake4/dart_eval/blob/master/CONTRIBUTING.md).\n\n## FAQ\n\n### How does it work?\n\n`dart_eval` is a fully Dart-based implementation of a bytecode compiler and runtime. \nFirst, the Dart analyzer is used to parse the code into an AST (abstract syntax tree). \nThen, the compiler looks at each of the declarations in turn, and recursively compiles\nto a linear bytecode format.\n\nFor evaluation dart_eval uses Dart's optimized dynamic dispatch. This means each bytecode\nis actually a class implementing `EvcOp` and we call its `run()` method to execute it.\nBytecodes can do things like push and pop values on the stack, add numbers, and jump to \nother places in the program, as well as more complex Dart-specific operations like \ncreate a class.\n\nSee the [in-depth overview wiki page](https://github.com/ethanblake4/dart_eval/wiki/In-depth-overview) for more information.\n\n### Does it support Flutter?\n\nYes! Check out [flutter_eval](https://pub.dev/packages/flutter_eval).\n\n### How fast is it?\n\nPreliminary testing shows that `dart_eval` running in AOT-compiled Dart \nis 10-50x slower than standard AOT Dart and is approximately on par with a \nlanguage like Ruby.\nIt's important to remember this only applies to code running directly in the \ndart_eval VM, and not any code it interacts with. For example, most Flutter apps spend \nthe vast majority of their performance budget in the Flutter framework itself, so the\nspeed impact of dart_eval is usually negligible.\n\n### Is this allowed in the App Store?\n\nThough Apple's official guidelines are unclear, many popular apps use similar\ntechniques to dynamically update their code. For example, apps built on\nReact Native often use its custom Hermes JavaScript engine to enable dynamic \ncode updates. Note that Apple is likely to remove apps if they introduce policy \nviolations in updates, regardless of the technology used.\n\n## Language feature support table\n\nThe following table details the language features supported by dart_eval with native Dart code. Feature support\nmay vary when bridging.\n\n| Feature | Support level | Tests |\n| ------- | ------------- | ----- |\n| Imports | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L144), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L176)  |\n| Exports | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L45), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L200) |\n| `part` / `part of` | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L76) |\n| `show` and `hide` | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L14) |\n| Conditional imports | ❌ | N/A |\n| Deferred imports | ❌ | N/A |\n| Functions | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L36) |\n| Anonymous functions | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L104), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L124), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L141), [[4]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L159), [[5]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L177), [[6]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L195) |\n| Arrow functions | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L237), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L249) |\n| Sync generators | ❌ | N/A |\n| Async generators | ❌ | N/A |\n| Tear-offs | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/tearoff_test.dart#L12), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/tearoff_test.dart#L31), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/tearoff_test.dart#L53) |\n| For loops | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L13), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L28) |\n| While loops | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L69) |\n| Do-while loops | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L86) |\n| For-each loops | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L54), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L71) |\n| Async for-each | ❌ | N/A |\n| Switch statements | ❌ | N/A |\n| Labels, `break` \u0026 `continue` | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L126), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L146) |\n| If statements | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L28) |\n| Try-catch | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L13), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#31), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#49), [[4]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#71), [[5]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#92) |\n| Try-catch-finally | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L132), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#147), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#187), [[4]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#209), [[5]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#231) |\n| Lists | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart) |\n| Iterable | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L29) |\n| Maps | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/convert_test.dart#L60), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L145), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L160), [[4]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L175) |\n| Sets | ❌ | N/A |\n| Collection `for` | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L76) |\n| Collection `if` | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L52) |\n| Spreads | ❌ | N/A |\n| Classes | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart) |\n| Class static methods | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L147), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L167) |\n| Getters and setters | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L253) |\n| Factory constructors | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L375) |\n| Redirecting constructors | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L474) |\n| `new` keyword | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L195) |\n| Class inheritance | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/functional1_test.dart) |\n| Abstract and `implements` | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/packages/hlc_test.dart#L8) |\n| `this` keyword | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L89), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L116) |\n| `super` keyword | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L319) |\n| Super constructor params | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L277) |\n| Mixins | ❌ | N/A |\n| Futures | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/async_test.dart#L69), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/async_test.dart#L88) |\n| Async/await | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/async_test.dart#L13), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/async_test.dart#L33), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/async_test.dart#L51) |\n| Streams | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/stdlib_test.dart#L172) |\n| String interpolation | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/stdlib_test.dart#L95) |\n| Enums | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/enum_test.dart#L12), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/enum_test.dart#L29), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/enum_test.dart#L48) |\n| Generic function types | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L302) |\n| Typedefs | ❌ | N/A |\n| Generic classes | Partial | ❌ |\n| Type tests (`is`) | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L12), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L44) |\n| Casting (`as`) | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L206), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L227), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L244) |\n| `assert` | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L259) |\n| Null safety | Partial | ❌ |\n| Late initialization | ❌ | N/A |\n| Cascades | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L136), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L160) |\n| Ternary expressions | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L118) |\n| Null coalescing expressions | ✅ | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L64), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/expression_test.dart#L186) |\n| Extension methods | ❌ | N/A |\n| Const expressions | Partial | N/A |\n| Isolates | ❌ | N/A |\n| Record types | ❌ | N/A |\n| Patterns | ❌ | N/A |\n\n## Features and bugs\n\nPlease file feature requests and bugs at the [issue tracker][tracker]. If you need help,\nuse the [discussion board][discussion].\n\n[tracker]: https://github.com/ethanblake4/dart_eval/issues\n[discussion]: https://github.com/ethanblake4/dart_eval/discussions\n","funding_links":[],"categories":["Dart"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethanblake4%2Fdart_eval","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fethanblake4%2Fdart_eval","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethanblake4%2Fdart_eval/lists"}