callLuaFunction method
List<LuaObject>
callLuaFunction(
- LuaObject obj, {
- List<
Object?> args = const [], - LuaExceptionCallback? onException,
inherited
Given a callable lua obj and a list of args, configure
a new scope with the provided args as parameters based on
the LuaObject.funcDef record. Args exceeding the parameter list
will be dropped. Any remaining parameters will be filled by
LuaObject.nil values. Any exceptions are caught and tracked
for the trace back later. The scope is popped and any return
result LuaObjects are returned as an argpack.
Implementation
List<LuaObject> callLuaFunction(
LuaObject obj, {
List<Object?> args = const [],
LuaExceptionCallback? onException,
}) {
LuaObject? callable;
if (obj.isFunc) {
callable = obj;
} else if (obj.isCallable) {
callable = switch (obj.readMetatable('__call')) {
final LuaObject lo => lo,
_ => null,
};
}
if (callable == null) {
final type = obj.luaTypeInfo;
final varname = obj.id;
throw 'Attempt to call a $type value "$varname".';
}
List<LuaObject> res = [];
final prevScope = scope;
pushScope(parent: callable.scope);
try {
final defArgs = callable.funcDef!.args;
final nilCount = defArgs.length - args.length;
for (int i = 0; i < defArgs.length; i++) {
final id = defArgs[i].lexeme;
defLocal(args[i]?.toLua(id) ?? LuaObject.nil(id));
}
for (int i = 0; i < nilCount; i++) {
defLocal(LuaObject.nil(defArgs[args.length + i].lexeme));
}
// For the public API utilites,
// we expect friendly non-null values.
// Return an empty list if null.
final temp = callable.call();
res = switch (temp) {
final List<LuaObject?> ls => ls.nonNulls.toList(),
final List<Object?> ls => ls.map((e) => e?.toLuaRet()).nonNulls.toList(),
final Object o => [o.toLuaRet()],
null => [],
};
} catch (e) {
if (e is LuaReturnValueException) {
res = e.argpack;
} else if (onException != null) {
onException.call(e);
} else {
rethrow;
}
} finally {
restoreScope(prevScope);
}
return res;
}