From 91b314d7f22155a7e156d5fe75668470bcd381f0 Mon Sep 17 00:00:00 2001
From: blueloveTH
Date: Thu, 2 Feb 2023 16:58:01 +0800
Subject: [PATCH] up
---
plugins/flutter/CHANGELOG.md | 4 +
plugins/flutter/README.md | 1 -
plugins/flutter/example/lib/main.dart | 3 +-
plugins/flutter/example/pubspec.lock | 2 +-
plugins/flutter/lib/jsonrpc.dart | 149 --------------------------
plugins/flutter/lib/no_web.dart | 106 +++++++++++++++---
plugins/flutter/lib/pocketpy.dart | 2 -
plugins/flutter/lib/web.dart | 77 ++++++++++---
plugins/flutter/pubspec.yaml | 2 +-
9 files changed, 158 insertions(+), 188 deletions(-)
delete mode 100644 plugins/flutter/lib/jsonrpc.dart
diff --git a/plugins/flutter/CHANGELOG.md b/plugins/flutter/CHANGELOG.md
index 91357401..199639a7 100644
--- a/plugins/flutter/CHANGELOG.md
+++ b/plugins/flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.8.0+1
+
++ Reconstruction
+
## 0.6.2+1
+ Break change
diff --git a/plugins/flutter/README.md b/plugins/flutter/README.md
index 0b40fb3c..4f1c7fd9 100644
--- a/plugins/flutter/README.md
+++ b/plugins/flutter/README.md
@@ -36,7 +36,6 @@ The features marked with `YES` are supported, and the features marked with `NO`
This plugin provides object-oriented interfaces including full functionality of PocketPy [C-API](https://pocketpy.dev/c-api/vm).
-It also provides `JsonRpcServer` class and `os` module bindings.
Run the following script to install this plugin.
diff --git a/plugins/flutter/example/lib/main.dart b/plugins/flutter/example/lib/main.dart
index 66da3eeb..42a42a3e 100644
--- a/plugins/flutter/example/lib/main.dart
+++ b/plugins/flutter/example/lib/main.dart
@@ -50,8 +50,7 @@ class _MyAppState extends State {
buffer.write(needMoreLines ? '... $text' : '>>> $text\n');
});
if (text == "exit()") exit(0);
- repl.input(text);
- needMoreLines = repl.last_input_result() == 0;
+ needMoreLines = repl.input(text) == 0;
refresh();
}
diff --git a/plugins/flutter/example/pubspec.lock b/plugins/flutter/example/pubspec.lock
index 80c7aefc..6fa18319 100644
--- a/plugins/flutter/example/pubspec.lock
+++ b/plugins/flutter/example/pubspec.lock
@@ -108,7 +108,7 @@ packages:
path: ".."
relative: true
source: path
- version: "0.6.1+2"
+ version: "0.8.0+1"
sky_engine:
dependency: transitive
description: flutter
diff --git a/plugins/flutter/lib/jsonrpc.dart b/plugins/flutter/lib/jsonrpc.dart
deleted file mode 100644
index 38e583fb..00000000
--- a/plugins/flutter/lib/jsonrpc.dart
+++ /dev/null
@@ -1,149 +0,0 @@
-// ignore_for_file: no_leading_underscores_for_local_identifiers, non_constant_identifier_names
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'no_web.dart' if (dart.library.html) 'web.dart';
-
-class _JsonRpcError {
- final Map payload = {};
-
- _JsonRpcError(int code, String message, {dynamic data}) {
- payload['code'] = code;
- payload['message'] = message;
- if (data != null) {
- payload['data'] = data;
- }
- }
-}
-
-class JsonRpcServer {
- final Map Function(List)> _methods = {};
-
- final void Function()? onPreDispatch;
- final void Function()? onPostDispatch;
- final bool enableFileAccess;
-
- JsonRpcServer(
- {this.onPreDispatch,
- this.onPostDispatch,
- this.enableFileAccess = false}) {
- if (!enableFileAccess) return;
- _registerOS(this);
- }
-
- /// Register a JSONRPC handler.
- void register(String name, FutureOr Function(List) method) {
- _methods[name] = method;
- }
-
- FutureOr _dispatch(ThreadedVM vm) {
- if (vm.state != ThreadState.suspended) throw Exception("Unexpected state");
- String? json = vm.read_jsonrpc_request();
- if (json == null) throw Exception("JSONRPC request is null");
- var request = jsonDecode(json);
- var f = _methods[request['method']];
- if (f == null) throw _JsonRpcError(-32601, "Method not found");
- try {
- return f(request['params'] as List);
- } catch (e) {
- throw _JsonRpcError(-32000, e.toString());
- }
- }
-
- /// Dispatch a JSONRPC request.
- FutureOr dispatch(ThreadedVM vm) async {
- onPreDispatch?.call();
- try {
- dynamic ret = _dispatch(vm);
- if (ret is Future) ret = await ret;
- vm.write_jsonrpc_response(jsonEncode({"result": ret}));
- onPostDispatch?.call();
- } on _JsonRpcError catch (e) {
- vm.write_jsonrpc_response(jsonEncode({"error": e.payload}));
- return;
- }
- }
-
- /// Attach the JsonRpcServer into a ThreadedVM. Once the ThreadedVM encounters JSONRPC request, it takes care of it automatically. This process will be stopped when the whole execution is done.
- Future attach(ThreadedVM vm,
- {Duration? spinFreq = const Duration(milliseconds: 20)}) async {
- while (vm.state.index <= ThreadState.running.index) {
- if (spinFreq != null) await Future.delayed(spinFreq);
- }
- switch (vm.state) {
- case ThreadState.suspended:
- await dispatch(vm);
- await attach(vm, spinFreq: spinFreq);
- break;
- case ThreadState.finished:
- break;
- default:
- throw Exception("Unexpected state");
- }
- }
-
- int _fileId = 0;
- final Map _files = {};
-
- void _registerOS(JsonRpcServer rpcServer) {
- rpcServer.register("fopen", (params) {
- var path = params[0];
- //var mode = params[1];
- var fp = File(path);
- _fileId += 1;
- _files[_fileId] = fp;
- return _fileId;
- });
-
- rpcServer.register("fclose", (params) {
- var fp = _files[params[0]];
- if (fp == null) throw Exception("FileIO was closed");
- _files.remove(params[0]);
- });
-
- rpcServer.register("fread", (params) {
- var fp = _files[params[0]];
- if (fp == null) throw Exception("FileIO was closed");
- return fp.readAsStringSync();
- });
-
- rpcServer.register("fwrite", (params) {
- var fp = _files[params[0]];
- if (fp == null) throw Exception("FileIO was closed");
- fp.writeAsStringSync(params[1]);
- });
-
- rpcServer.register("os.listdir", (params) {
- String path = params[0];
- var entries = Directory(path).listSync(followLinks: false);
- var ret = entries.map((e) {
- return e.path.split(Platform.pathSeparator).last;
- }).toList();
- return ret;
- });
-
- rpcServer.register("os.mkdir", (params) {
- String path = params[0];
- Directory(path).createSync();
- });
-
- rpcServer.register("os.rmdir", (params) {
- String path = params[0];
- Directory(path).deleteSync(recursive: true);
- });
-
- rpcServer.register("os.remove", (params) {
- String path = params[0];
- File(path).deleteSync();
- });
-
- rpcServer.register("os.path.exists", (params) {
- String path = params[0];
- bool _0 = Directory(path).existsSync();
- bool _1 = File(path).existsSync();
- return (_0 || _1);
- });
- }
-}
diff --git a/plugins/flutter/lib/no_web.dart b/plugins/flutter/lib/no_web.dart
index 247d1f20..1e848a99 100644
--- a/plugins/flutter/lib/no_web.dart
+++ b/plugins/flutter/lib/no_web.dart
@@ -6,8 +6,7 @@ import 'dart:io';
import 'package:ffi/ffi.dart';
import 'common.dart';
-class _Bindings
-{
+class _Bindings {
static ffi.DynamicLibrary _load() {
String _libName = "pocketpy";
if (Platform.isIOS) {
@@ -24,20 +23,98 @@ class _Bindings
static final _lib = _load();
- static final pkpy_delete = _lib.lookupFunction("pkpy_delete");
- static final pkpy_new_repl = _lib.lookupFunction("pkpy_new_repl");
- static final pkpy_repl_input = _lib.lookupFunction line), int Function(ffi.Pointer r, ffi.Pointer line)>("pkpy_repl_input");
- static final pkpy_new_vm = _lib.lookupFunction("pkpy_new_vm");
- static final pkpy_vm_add_module = _lib.lookupFunction name, ffi.Pointer source), void Function(ffi.Pointer vm, ffi.Pointer name, ffi.Pointer source)>("pkpy_vm_add_module");
- static final pkpy_vm_eval = _lib.lookupFunction Function(ffi.Pointer vm, ffi.Pointer source), ffi.Pointer Function(ffi.Pointer vm, ffi.Pointer source)>("pkpy_vm_eval");
- static final pkpy_vm_exec = _lib.lookupFunction source), void Function(ffi.Pointer vm, ffi.Pointer source)>("pkpy_vm_exec");
- static final pkpy_vm_get_global = _lib.lookupFunction Function(ffi.Pointer vm, ffi.Pointer name), ffi.Pointer Function(ffi.Pointer vm, ffi.Pointer name)>("pkpy_vm_get_global");
- static final pkpy_vm_read_output = _lib.lookupFunction Function(ffi.Pointer vm), ffi.Pointer Function(ffi.Pointer vm)>("pkpy_vm_read_output");
+ static final pkpy_delete = _lib.lookupFunction<
+ ffi.Void Function(ffi.Pointer p),
+ void Function(ffi.Pointer p)>("pkpy_delete");
+ static final pkpy_new_repl = _lib.lookupFunction<
+ ffi.Pointer Function(ffi.Pointer vm),
+ ffi.Pointer Function(ffi.Pointer vm)>("pkpy_new_repl");
+ static final pkpy_repl_input = _lib.lookupFunction<
+ ffi.Int32 Function(ffi.Pointer r, ffi.Pointer line),
+ int Function(ffi.Pointer r, ffi.Pointer line)>("pkpy_repl_input");
+ static final pkpy_new_vm = _lib.lookupFunction<
+ ffi.Pointer Function(ffi.Bool use_stdio),
+ ffi.Pointer Function(bool use_stdio)>("pkpy_new_vm");
+ static final pkpy_vm_add_module = _lib.lookupFunction<
+ ffi.Void Function(
+ ffi.Pointer vm, ffi.Pointer name, ffi.Pointer source),
+ void Function(ffi.Pointer vm, ffi.Pointer name,
+ ffi.Pointer source)>("pkpy_vm_add_module");
+ static final pkpy_vm_eval = _lib.lookupFunction<
+ ffi.Pointer Function(ffi.Pointer vm, ffi.Pointer source),
+ ffi.Pointer Function(
+ ffi.Pointer vm, ffi.Pointer source)>("pkpy_vm_eval");
+ static final pkpy_vm_exec = _lib.lookupFunction<
+ ffi.Void Function(ffi.Pointer vm, ffi.Pointer source),
+ void Function(ffi.Pointer vm, ffi.Pointer source)>("pkpy_vm_exec");
+ static final pkpy_vm_get_global = _lib.lookupFunction<
+ ffi.Pointer Function(ffi.Pointer vm, ffi.Pointer name),
+ ffi.Pointer Function(
+ ffi.Pointer vm, ffi.Pointer name)>("pkpy_vm_get_global");
+ static final pkpy_vm_read_output = _lib.lookupFunction<
+ ffi.Pointer Function(ffi.Pointer vm),
+ ffi.Pointer Function(ffi.Pointer vm)>("pkpy_vm_read_output");
}
+class _Str {
+ static final Finalizer> finalizer =
+ Finalizer((p) => malloc.free(p));
+
+ late final ffi.Pointer _p;
+ _Str(String s) {
+ _p = s.toNativeUtf8();
+ finalizer.attach(this, _p);
+ }
+
+ ffi.Pointer get p => _p;
+}
+
+class VM {
+ late final pointer = _Bindings.pkpy_new_vm(false);
+
+ void dispose() {
+ _Bindings.pkpy_delete(pointer);
+ }
+
+ PyOutput read_output() {
+ var _o = _Bindings.pkpy_vm_read_output(pointer);
+ String _j = _o.toDartString();
+ var ret = PyOutput.fromJson(cvt.jsonDecode(_j));
+ _Bindings.pkpy_delete(_o);
+ return ret;
+ }
+
+ /// Add a source module into a virtual machine.
+ void add_module(String name, String source) {
+ _Bindings.pkpy_vm_add_module(pointer, _Str(name).p, _Str(source).p);
+ }
+
+ /// Evaluate an expression. Return `__repr__` of the result. If there is any error, return `nullptr`.
+ String? eval(String source) {
+ var ret = _Bindings.pkpy_vm_eval(pointer, _Str(source).p);
+ if (ret == ffi.nullptr) return null;
+ String s = ret.toDartString();
+ _Bindings.pkpy_delete(ret);
+ return s;
+ }
+
+ /// Run a given source on a virtual machine.
+ void exec(String source) {
+ _Bindings.pkpy_vm_exec(pointer, _Str(source).p);
+ }
+
+ /// Get a global variable of a virtual machine. Return `__repr__` of the result. If the variable is not found, return `nullptr`.
+ String? get_global(String name) {
+ var ret = _Bindings.pkpy_vm_get_global(pointer, _Str(name).p);
+ if (ret == ffi.nullptr) return null;
+ String s = ret.toDartString();
+ _Bindings.pkpy_delete(ret);
+ return s;
+ }
+}
class REPL {
- late final ffi.Pointer pointer;
+ late final dynamic pointer;
REPL(VM vm) {
pointer = _Bindings.pkpy_new_repl(vm.pointer);
@@ -48,11 +125,8 @@ class REPL {
}
/// Input a source line to an interactive console.
- int input(String line)
- {
+ int input(String line) {
var ret = _Bindings.pkpy_repl_input(pointer, _Str(line).p);
return ret;
}
-
}
-
diff --git a/plugins/flutter/lib/pocketpy.dart b/plugins/flutter/lib/pocketpy.dart
index 84ed9c8f..9b52a027 100644
--- a/plugins/flutter/lib/pocketpy.dart
+++ b/plugins/flutter/lib/pocketpy.dart
@@ -1,5 +1,3 @@
library pocketpy;
-
-export 'jsonrpc.dart';
export 'common.dart';
export 'no_web.dart' if (dart.library.html) 'web.dart';
\ No newline at end of file
diff --git a/plugins/flutter/lib/web.dart b/plugins/flutter/lib/web.dart
index d1053eb4..d21464f6 100644
--- a/plugins/flutter/lib/web.dart
+++ b/plugins/flutter/lib/web.dart
@@ -4,19 +4,67 @@ import 'package:js/js.dart';
import 'common.dart';
@JS("Module.ccall")
-external dynamic ccall(String name, String? returnType, List argTypes, List args);
+external dynamic ccall(
+ String name, String? returnType, List argTypes, List args);
-class _Bindings
-{
- static final pkpy_delete = (dynamic p) => ccall("pkpy_delete", null, ["number"], [p]);
- static final pkpy_new_repl = (dynamic vm) => ccall("pkpy_new_repl", "number", ["number"], [vm]);
- static final pkpy_repl_input = (dynamic r, String line) => ccall("pkpy_repl_input", "number", ["number", "string"], [r, line]);
- static final pkpy_new_vm = (bool use_stdio) => ccall("pkpy_new_vm", "number", ["boolean"], [use_stdio]);
- static final pkpy_vm_add_module = (dynamic vm, String name, String source) => ccall("pkpy_vm_add_module", null, ["number", "string", "string"], [vm, name, source]);
- static final pkpy_vm_eval = (dynamic vm, String source) => ccall("pkpy_vm_eval", "string", ["number", "string"], [vm, source]);
- static final pkpy_vm_exec = (dynamic vm, String source) => ccall("pkpy_vm_exec", null, ["number", "string"], [vm, source]);
- static final pkpy_vm_get_global = (dynamic vm, String name) => ccall("pkpy_vm_get_global", "string", ["number", "string"], [vm, name]);
- static final pkpy_vm_read_output = (dynamic vm) => ccall("pkpy_vm_read_output", "string", ["number"], [vm]);
+class _Bindings {
+ static final pkpy_delete =
+ (dynamic p) => ccall("pkpy_delete", null, ["number"], [p]);
+ static final pkpy_new_repl =
+ (dynamic vm) => ccall("pkpy_new_repl", "number", ["number"], [vm]);
+ static final pkpy_repl_input = (dynamic r, String line) =>
+ ccall("pkpy_repl_input", "number", ["number", "string"], [r, line]);
+ static final pkpy_new_vm = (bool use_stdio) =>
+ ccall("pkpy_new_vm", "number", ["boolean"], [use_stdio]);
+ static final pkpy_vm_add_module = (dynamic vm, String name, String source) =>
+ ccall("pkpy_vm_add_module", null, ["number", "string", "string"],
+ [vm, name, source]);
+ static final pkpy_vm_eval = (dynamic vm, String source) =>
+ ccall("pkpy_vm_eval", "string", ["number", "string"], [vm, source]);
+ static final pkpy_vm_exec = (dynamic vm, String source) =>
+ ccall("pkpy_vm_exec", null, ["number", "string"], [vm, source]);
+ static final pkpy_vm_get_global = (dynamic vm, String name) =>
+ ccall("pkpy_vm_get_global", "string", ["number", "string"], [vm, name]);
+ static final pkpy_vm_read_output =
+ (dynamic vm) => ccall("pkpy_vm_read_output", "string", ["number"], [vm]);
+}
+
+class VM {
+ late final pointer = _Bindings.pkpy_new_vm(false);
+
+ void dispose() {
+ _Bindings.pkpy_delete(pointer);
+ }
+
+ PyOutput read_output() {
+ var _o = _Bindings.pkpy_vm_read_output(pointer);
+ String _j = _o;
+ var ret = PyOutput.fromJson(cvt.jsonDecode(_j));
+
+ return ret;
+ }
+
+ /// Add a source module into a virtual machine.
+ void add_module(String name, String source) {
+ _Bindings.pkpy_vm_add_module(pointer, name, source);
+ }
+
+ /// Evaluate an expression. Return `__repr__` of the result. If there is any error, return `nullptr`.
+ String? eval(String source) {
+ var ret = _Bindings.pkpy_vm_eval(pointer, source);
+ return ret;
+ }
+
+ /// Run a given source on a virtual machine.
+ void exec(String source) {
+ _Bindings.pkpy_vm_exec(pointer, source);
+ }
+
+ /// Get a global variable of a virtual machine. Return `__repr__` of the result. If the variable is not found, return `nullptr`.
+ String? get_global(String name) {
+ var ret = _Bindings.pkpy_vm_get_global(pointer, name);
+ return ret;
+ }
}
class REPL {
@@ -31,11 +79,8 @@ class REPL {
}
/// Input a source line to an interactive console.
- int input(String line)
- {
+ int input(String line) {
var ret = _Bindings.pkpy_repl_input(pointer, line);
return ret;
}
-
}
-
diff --git a/plugins/flutter/pubspec.yaml b/plugins/flutter/pubspec.yaml
index d271c4b2..7ce2bb51 100644
--- a/plugins/flutter/pubspec.yaml
+++ b/plugins/flutter/pubspec.yaml
@@ -1,6 +1,6 @@
name: pocketpy
description: A lightweight Python interpreter for game engines.
-version: 0.6.2+1
+version: 0.8.0+1
homepage: https://pocketpy.dev
repository: https://github.com/blueloveth/pocketpy