no_web.dart 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // ignore_for_file: non_constant_identifier_names, prefer_typing_uninitialized_variables, constant_identifier_names, no_leading_underscores_for_local_identifiers
  2. import 'dart:convert' as cvt;
  3. import 'dart:ffi' as ffi;
  4. import 'dart:io';
  5. import 'package:ffi/ffi.dart';
  6. import 'common.dart';
  7. class _Bindings {
  8. static ffi.DynamicLibrary _load() {
  9. String _libName = "pocketpy";
  10. if (Platform.isIOS) {
  11. return ffi.DynamicLibrary.process();
  12. }
  13. if (Platform.isAndroid || Platform.isLinux) {
  14. return ffi.DynamicLibrary.open('lib$_libName.so');
  15. }
  16. if (Platform.isWindows) {
  17. return ffi.DynamicLibrary.open('$_libName.dll');
  18. }
  19. throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
  20. }
  21. static final _lib = _load();
  22. static final pkpy_delete = _lib.lookupFunction<
  23. ffi.Void Function(ffi.Pointer p),
  24. void Function(ffi.Pointer p)>("pkpy_delete");
  25. static final pkpy_new_repl = _lib.lookupFunction<
  26. ffi.Pointer Function(ffi.Pointer vm),
  27. ffi.Pointer Function(ffi.Pointer vm)>("pkpy_new_repl");
  28. static final pkpy_repl_input = _lib.lookupFunction<
  29. ffi.Int32 Function(ffi.Pointer r, ffi.Pointer<Utf8> line),
  30. int Function(ffi.Pointer r, ffi.Pointer<Utf8> line)>("pkpy_repl_input");
  31. static final pkpy_new_vm = _lib.lookupFunction<
  32. ffi.Pointer Function(ffi.Bool use_stdio),
  33. ffi.Pointer Function(bool use_stdio)>("pkpy_new_vm");
  34. static final pkpy_vm_add_module = _lib.lookupFunction<
  35. ffi.Void Function(
  36. ffi.Pointer vm, ffi.Pointer<Utf8> name, ffi.Pointer<Utf8> source),
  37. void Function(ffi.Pointer vm, ffi.Pointer<Utf8> name,
  38. ffi.Pointer<Utf8> source)>("pkpy_vm_add_module");
  39. static final pkpy_vm_eval = _lib.lookupFunction<
  40. ffi.Pointer<Utf8> Function(ffi.Pointer vm, ffi.Pointer<Utf8> source),
  41. ffi.Pointer<Utf8> Function(
  42. ffi.Pointer vm, ffi.Pointer<Utf8> source)>("pkpy_vm_eval");
  43. static final pkpy_vm_exec = _lib.lookupFunction<
  44. ffi.Void Function(ffi.Pointer vm, ffi.Pointer<Utf8> source),
  45. void Function(ffi.Pointer vm, ffi.Pointer<Utf8> source)>("pkpy_vm_exec");
  46. static final pkpy_vm_get_global = _lib.lookupFunction<
  47. ffi.Pointer<Utf8> Function(ffi.Pointer vm, ffi.Pointer<Utf8> name),
  48. ffi.Pointer<Utf8> Function(
  49. ffi.Pointer vm, ffi.Pointer<Utf8> name)>("pkpy_vm_get_global");
  50. static final pkpy_vm_read_output = _lib.lookupFunction<
  51. ffi.Pointer<Utf8> Function(ffi.Pointer vm),
  52. ffi.Pointer<Utf8> Function(ffi.Pointer vm)>("pkpy_vm_read_output");
  53. }
  54. class _Str {
  55. static final Finalizer<ffi.Pointer<Utf8>> finalizer =
  56. Finalizer((p) => malloc.free(p));
  57. late final ffi.Pointer<Utf8> _p;
  58. _Str(String s) {
  59. _p = s.toNativeUtf8();
  60. finalizer.attach(this, _p);
  61. }
  62. ffi.Pointer<Utf8> get p => _p;
  63. }
  64. class VM {
  65. late final pointer = _Bindings.pkpy_new_vm(false);
  66. void dispose() {
  67. _Bindings.pkpy_delete(pointer);
  68. }
  69. PyOutput read_output() {
  70. var _o = _Bindings.pkpy_vm_read_output(pointer);
  71. String _j = _o.toDartString();
  72. var ret = PyOutput.fromJson(cvt.jsonDecode(_j));
  73. _Bindings.pkpy_delete(_o);
  74. return ret;
  75. }
  76. /// Add a source module into a virtual machine.
  77. void add_module(String name, String source) {
  78. _Bindings.pkpy_vm_add_module(pointer, _Str(name).p, _Str(source).p);
  79. }
  80. /// Evaluate an expression. Return `__repr__` of the result. If there is any error, return `nullptr`.
  81. String? eval(String source) {
  82. var ret = _Bindings.pkpy_vm_eval(pointer, _Str(source).p);
  83. if (ret == ffi.nullptr) return null;
  84. String s = ret.toDartString();
  85. _Bindings.pkpy_delete(ret);
  86. return s;
  87. }
  88. /// Run a given source on a virtual machine.
  89. void exec(String source) {
  90. _Bindings.pkpy_vm_exec(pointer, _Str(source).p);
  91. }
  92. /// Get a global variable of a virtual machine. Return `__repr__` of the result. If the variable is not found, return `nullptr`.
  93. String? get_global(String name) {
  94. var ret = _Bindings.pkpy_vm_get_global(pointer, _Str(name).p);
  95. if (ret == ffi.nullptr) return null;
  96. String s = ret.toDartString();
  97. _Bindings.pkpy_delete(ret);
  98. return s;
  99. }
  100. }
  101. class REPL {
  102. late final dynamic pointer;
  103. REPL(VM vm) {
  104. pointer = _Bindings.pkpy_new_repl(vm.pointer);
  105. }
  106. void dispose() {
  107. _Bindings.pkpy_delete(pointer);
  108. }
  109. /// Input a source line to an interactive console.
  110. int input(String line) {
  111. var ret = _Bindings.pkpy_repl_input(pointer, _Str(line).p);
  112. return ret;
  113. }
  114. }