Skip to content

Async support #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
include: package:lints/recommended.yaml

analyzer:
strong-mode:
# implicit-casts: false
# implicit-dynamic: false

linter:
rules:
- unawaited_futures
- await_only_futures
73 changes: 73 additions & 0 deletions example/async_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'dart:async';
import 'dart:io';

import 'package:lua_dardo/lua.dart';

void main(List<String> args) async {
print("Starting");
final chunk = await File("example/async_example.lua").readAsString();

await LuaWorker(
chunk: chunk,
data: {"input": ""},
).run();
}

class LuaWorker {
late final LuaState ls;
final String chunk;
final Map<String, dynamic> data;

final _ready = Completer();

LuaWorker({required this.chunk, required this.data}) {
ls = LuaState.newState();

ls.openLibs().then((value) {
ls.register('sleep', luaSleep);
ls.register('dprint', luaPrint);

_ready.complete();
}); // allow all std Lua libs
}

Future<void> run() async {
await _ready.future;

for (final d in data.keys) {
final val = data[d];
if (val is String) {
ls.pushString(d);
} else if (val is int) {
ls.pushInteger(val);
} else if (val is bool) {
ls.pushBoolean(val);
}
// Set variable name
ls.setGlobal(d);
}

ls.loadString(chunk);

await ls.call(0, 0);
print("lua call done --- goodbye");
}

FutureOr<int> luaSleep(LuaState ls) async {
print("start Dart Sleep for Lua");
final delayInMs = ls.checkInteger(1);
ls.pop(1);

await Future<void>.delayed(Duration(milliseconds: delayInMs ?? 1));
print("end Dart Sleep for Lua");
return 1;
}

int luaPrint(LuaState ls) {
final val = ls.checkInteger(1);
ls.pop(1);

print("lua print:$val");
return 1;
}
}
14 changes: 14 additions & 0 deletions example/async_example.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
sleep(3000)

function add (b)
local a = 1
while( a < b ) do
print("a value is", a)
a = a + 1
end
return a
end

b = add(3)
dprint(b)
print("lua finished")
7 changes: 3 additions & 4 deletions example/example.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import 'package:lua_dardo/lua.dart';


void main(List<String> arguments) {
void main(List<String> arguments) async {
LuaState state = LuaState.newState();
state.openLibs();
await state.openLibs();
state.loadString(r'''
a=10
while( a < 20 ) do
print("a value is", a)
a = a+1
end
''');
state.call(0, 0);
await state.call(0, 0);
}
2 changes: 1 addition & 1 deletion lib/src/api/lua_aux_lib.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ abstract class LuaAuxLib {

bool callMeta(int obj, String e);

void openLibs();
Future<void> openLibs();

int ref (int t);
void unRef (int t, int ref);
Expand Down
3 changes: 2 additions & 1 deletion lib/src/api/lua_basic_api.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:typed_data';

import '../state/lua_userdata.dart';
Expand Down Expand Up @@ -144,7 +145,7 @@ abstract class LuaBasicAPI {
/* 'load' and 'call' functions (load and run Lua code) */
ThreadStatus load(Uint8List chunk, String chunkName, String? mode);

void call(int nArgs, int nResults);
FutureOr<void> call(int nArgs, int nResults);

ThreadStatus pCall(int nArgs, int nResults, int msgh);

Expand Down
4 changes: 3 additions & 1 deletion lib/src/api/lua_type.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'lua_state.dart';

/// basic ypes
Expand Down Expand Up @@ -51,4 +53,4 @@ enum ThreadStatus {
luaErrFile,
}

typedef DartFunction = int Function(LuaState ls);
typedef DartFunction = FutureOr<int> Function(LuaState ls);
56 changes: 28 additions & 28 deletions lib/src/state/lua_state_impl.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:io';
Expand Down Expand Up @@ -540,7 +541,7 @@ class LuaStateImpl implements LuaState, LuaVM {
}

@override
void call(int nArgs, int nResults) {
FutureOr<void> call(int nArgs, int nResults) async {
Object? val = _stack!.get(-(nArgs + 1));
Object? f = val is Closure ? val : null;

Expand All @@ -557,16 +558,16 @@ class LuaStateImpl implements LuaState, LuaVM {
if (f != null) {
Closure c = f as Closure;
if (c.proto != null) {
_callLuaClosure(nArgs, nResults, c);
await _callLuaClosure(nArgs, nResults, c);
} else {
_callDartClosure(nArgs, nResults, c);
await _callDartClosure(nArgs, nResults, c);
}
} else {
throw Exception("not function!");
}
}

void _callLuaClosure(int nArgs, int nResults, Closure c) {
Future<void> _callLuaClosure(int nArgs, int nResults, Closure c) async {
int nRegs = c.proto!.maxStackSize;
int nParams = c.proto!.numParams!;
bool isVararg = c.proto!.isVararg == 1;
Expand All @@ -586,7 +587,7 @@ class LuaStateImpl implements LuaState, LuaVM {
// run closure
_pushLuaStack(newStack);
setTop(nRegs);
_runLuaClosure();
await _runLuaClosure();
_popLuaStack();

// return results
Expand All @@ -597,7 +598,7 @@ class LuaStateImpl implements LuaState, LuaVM {
}
}

void _callDartClosure(int nArgs, int nResults, Closure c) {
Future<void> _callDartClosure(int nArgs, int nResults, Closure c) async {
// create new lua stack
LuaStack newStack = new LuaStack(/*nRegs+LUA_MINSTACK*/);
newStack.state = this;
Expand All @@ -611,7 +612,8 @@ class LuaStateImpl implements LuaState, LuaVM {

// run closure
_pushLuaStack(newStack);
int r = c.dartFunc!.call(this);
int r = await Future.value(c.dartFunc!.call(this));

_popLuaStack();

// return results
Expand All @@ -622,11 +624,14 @@ class LuaStateImpl implements LuaState, LuaVM {
}
}

void _runLuaClosure() {
Future<void> _runLuaClosure() async {
for (;;) {
int i = fetch();
OpCode opCode = Instruction.getOpCode(i);
opCode.action!.call(i, this);
final r = opCode.action!.call(i, this);
if (r is Future) {
await r;
}
if (opCode.name == "RETURN") {
break;
}
Expand All @@ -635,9 +640,8 @@ class LuaStateImpl implements LuaState, LuaVM {

@override
ThreadStatus load(Uint8List chunk, String chunkName, String? mode) {
Prototype proto = BinaryChunk.isBinaryChunk(chunk)
? BinaryChunk.unDump(chunk)
: Compiler.compile(utf8.decode(chunk), chunkName);
Prototype proto =
BinaryChunk.isBinaryChunk(chunk) ? BinaryChunk.unDump(chunk) : Compiler.compile(utf8.decode(chunk), chunkName);
Closure closure = Closure(proto);
_stack!.push(closure);
if (proto.upvalues.length > 0) {
Expand Down Expand Up @@ -924,14 +928,12 @@ class LuaStateImpl implements LuaState, LuaVM {

@override
bool doFile(String filename) {
return loadFile(filename) == ThreadStatus.luaOk &&
pCall(0, luaMultret, 0) == ThreadStatus.luaOk;
return loadFile(filename) == ThreadStatus.luaOk && pCall(0, luaMultret, 0) == ThreadStatus.luaOk;
}

@override
bool doString(String str) {
return loadString(str) == ThreadStatus.luaOk &&
pCall(0, luaMultret, 0) == ThreadStatus.luaOk;
return loadString(str) == ThreadStatus.luaOk && pCall(0, luaMultret, 0) == ThreadStatus.luaOk;
}

@override
Expand Down Expand Up @@ -1012,7 +1014,7 @@ class LuaStateImpl implements LuaState, LuaVM {
@override
void newLib(Map l) {
newLibTable(l);
setFuncs(l as Map<String, int Function(LuaState)?>, 0);
setFuncs(l as Map<String, FutureOr<int> Function(LuaState)?>, 0);
}

@override
Expand All @@ -1021,7 +1023,7 @@ class LuaStateImpl implements LuaState, LuaVM {
}

@override
void openLibs() {
Future<void> openLibs() async {
Map<String, DartFunction> libs = <String, DartFunction>{
"_G": BasicLib.openBaseLib,
"package": PackageLib.openPackageLib,
Expand All @@ -1030,11 +1032,11 @@ class LuaStateImpl implements LuaState, LuaVM {
"math": MathLib.openMathLib,
"os": OSLib.openOSLib
};

libs.forEach((name, fun) {
requireF(name, fun, true);
for (final entry in libs.entries) {
await requireF(entry.key, entry.value, true);
pop(1);
});
}
}

@override
Expand All @@ -1059,15 +1061,15 @@ class LuaStateImpl implements LuaState, LuaVM {
}

@override
void requireF(String modname, openf, bool glb) {
FutureOr<void> requireF(String modname, openf, bool glb) async {
getSubTable(luaRegistryIndex, "_LOADED");
getField(-1, modname); /* LOADED[modname] */
if (!toBoolean(-1)) {
/* package not already loaded? */
pop(1); /* remove field */
pushDartFunction(openf);
pushString(modname); /* argument to open function */
call(1, 1); /* call 'openf' to open module */
await call(1, 1); /* call 'openf' to open module */
pushValue(-1); /* make copy of module (call result) */
setField(-3, modname); /* _LOADED[modname] = module */
}
Expand Down Expand Up @@ -1148,8 +1150,7 @@ class LuaStateImpl implements LuaState, LuaVM {
default:
LuaType tt = getMetafield(idx, "__name");
/* try name */
String? kind =
tt == LuaType.luaString ? checkString(-1) : typeName2(idx);
String? kind = tt == LuaType.luaString ? checkString(-1) : typeName2(idx);
pushString("$kind: ${toPointer(idx).hashCode}");
if (tt != LuaType.luaNil) {
remove(-2); /* remove '__name' */
Expand Down Expand Up @@ -1275,8 +1276,7 @@ class LuaStateImpl implements LuaState, LuaVM {

@override
void loadVararg(int n) {
List<Object?>? varargs =
_stack!.varargs != null ? _stack!.varargs : const <Object>[];
List<Object?>? varargs = _stack!.varargs != null ? _stack!.varargs : const <Object>[];
if (n < 0) {
n = varargs!.length;
}
Expand Down
5 changes: 3 additions & 2 deletions lib/src/stdlib/basic_lib.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
Expand Down Expand Up @@ -49,13 +50,13 @@ class BasicLib {
// print (···)
// http://www.lua.org/manual/5.3/manual.html#pdf-print
// lua-5.3.4/src/lbaselib.c#luaB_print()
static int _basePrint(LuaState ls) {
static FutureOr<int> _basePrint(LuaState ls) async {
int n = ls.getTop(); /* number of arguments */
ls.getGlobal('tostring');
for (int i = 1; i <= n; i++) {
ls.pushValue(-1); /* function to be called */
ls.pushValue(i); /* value to print */
ls.call(1, 1);
await ls.call(1, 1);
String? s = ls.toStr(-1); /* get result */
if (s == null) {
return ls.error2("'tostring' must return a string to 'print'");
Expand Down
6 changes: 4 additions & 2 deletions lib/src/vm/instructions.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import '../api/lua_state.dart';
import '../api/lua_type.dart';
import '../api/lua_vm.dart';
Expand Down Expand Up @@ -407,12 +409,12 @@ class Instructions {
}

// R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
static void call(int i, LuaVM vm) {
static FutureOr<void> call(int i, LuaVM vm) async {
int a = Instruction.getA(i) + 1;
int b = Instruction.getB(i);
int c = Instruction.getC(i);
int nArgs = pushFuncAndArgs(a, b, vm);
vm.call(nArgs, c - 1);
await Future.value(vm.call(nArgs, c - 1));
popResults(a, c, vm);
}

Expand Down
3 changes: 2 additions & 1 deletion lib/src/vm/opcodes.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'dart:async';

import '../api/lua_vm.dart';
import 'instructions.dart';

typedef OpAction = void Function(int i, LuaVM vm);
typedef OpAction = FutureOr<void> Function(int i, LuaVM vm);

enum OpMode {
iABC, // [ B:9 ][ C:9 ][ A:8 ][OP:6]
Expand Down