command: implement callable bytecode functions
This commit is contained in:
@@ -17,6 +17,11 @@ static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static void fini(fx_object *obj, void *priv)
|
||||
{
|
||||
struct bshell_command_p *cmd = priv;
|
||||
}
|
||||
|
||||
static void command_set_args(
|
||||
struct bshell_command_p *cmd,
|
||||
fx_value *args,
|
||||
@@ -283,5 +288,6 @@ FX_TYPE_DEFINITION_BEGIN(bshell_command)
|
||||
FX_TYPE_NAME("bshell.runtime.command");
|
||||
FX_TYPE_CLASS(bshell_command_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_FINI(fini);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_command_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_command)
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
#include <bshell/command/command.h>
|
||||
#include <bshell/command/function.h>
|
||||
#include <bshell/runtime/pipeline.h>
|
||||
#include <bshell/runtime/runtime.h>
|
||||
#include <bshell/runtime/script-block.h>
|
||||
#include <bshell/status.h>
|
||||
#include <fx/collections/array.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
struct bshell_function_p {
|
||||
char *func_name;
|
||||
fx_array *func_positional_params;
|
||||
bshell_scriptblock *func_body;
|
||||
};
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
struct bshell_function_p *func_p = priv;
|
||||
func_p->func_positional_params = fx_array_create();
|
||||
func_p->func_body = bshell_scriptblock_create();
|
||||
}
|
||||
|
||||
static void fini(fx_object *obj, void *priv)
|
||||
{
|
||||
struct bshell_function_p *func_p = priv;
|
||||
if (func_p->func_name) {
|
||||
free(func_p->func_name);
|
||||
}
|
||||
|
||||
fx_array_unref(func_p->func_positional_params);
|
||||
bshell_scriptblock_unref(func_p->func_body);
|
||||
}
|
||||
|
||||
static enum bshell_status get_callable_name(
|
||||
const bshell_function *func,
|
||||
fx_string *out)
|
||||
{
|
||||
struct bshell_function_p *func_p
|
||||
= fx_object_get_private(func, BSHELL_TYPE_FUNCTION);
|
||||
fx_string_append_cstrf(out, "%s", func_p->func_name);
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status begin_processing(bshell_command *cmd)
|
||||
{
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status process_record(
|
||||
bshell_command *cmd,
|
||||
bshell_pipeline *pipeline,
|
||||
struct bshell_runtime *rt)
|
||||
{
|
||||
struct bshell_function_p *func_p
|
||||
= fx_object_get_private(cmd, BSHELL_TYPE_FUNCTION);
|
||||
bshell_runtime_push_scope(rt, func_p->func_body);
|
||||
|
||||
const fx_iterator *param_it
|
||||
= fx_iterator_begin(func_p->func_positional_params);
|
||||
size_t i = 1;
|
||||
fx_foreach(v, param_it)
|
||||
{
|
||||
fx_string *param = NULL;
|
||||
fx_value_get_object(v, ¶m);
|
||||
|
||||
const fx_value *arg = bshell_command_get_arg(cmd, i);
|
||||
if (!arg) {
|
||||
break;
|
||||
}
|
||||
|
||||
bshell_variable *var = bshell_runtime_define_var(
|
||||
rt,
|
||||
fx_string_get_cstr(param));
|
||||
bshell_variable_set_value(var, *arg);
|
||||
}
|
||||
fx_iterator_unref(param_it);
|
||||
#if 0
|
||||
bshell_variable *item = bshell_runtime_define_var(rt, "_");
|
||||
bshell_variable_set_value(item, &in);
|
||||
#endif
|
||||
|
||||
fx_value out = bshell_runtime_eval(rt);
|
||||
bshell_runtime_pop_scope(rt);
|
||||
if (fx_value_is_set(&out)) {
|
||||
bshell_pipeline_write_value(pipeline, out, false);
|
||||
fx_value_unset(&out);
|
||||
}
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status end_processing(bshell_command *cmd)
|
||||
{
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
bshell_function *bshell_function_create(const char *name)
|
||||
{
|
||||
bshell_function *out = fx_object_create(BSHELL_TYPE_FUNCTION);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bshell_function_p *func
|
||||
= fx_object_get_private(out, BSHELL_TYPE_FUNCTION);
|
||||
func->func_name = fx_strdup(name);
|
||||
if (!func->func_name) {
|
||||
bshell_function_unref(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void bshell_function_add_positional_parameter(
|
||||
bshell_function *func,
|
||||
const char *name)
|
||||
{
|
||||
fx_string *str = fx_string_create_from_cstr(name);
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct bshell_function_p *func_p
|
||||
= fx_object_get_private(func, BSHELL_TYPE_FUNCTION);
|
||||
fx_array_push_back(
|
||||
func_p->func_positional_params,
|
||||
FX_VALUE_OBJECT(str));
|
||||
fx_string_unref(str);
|
||||
}
|
||||
|
||||
static const char *function_get_name(const struct bshell_function_p *func)
|
||||
{
|
||||
return func->func_name;
|
||||
}
|
||||
|
||||
static const fx_array *function_get_positional_parameters(
|
||||
const struct bshell_function_p *func)
|
||||
{
|
||||
return func->func_positional_params;
|
||||
}
|
||||
|
||||
static bshell_scriptblock *function_get_body(struct bshell_function_p *func)
|
||||
{
|
||||
return func->func_body;
|
||||
}
|
||||
|
||||
const char *bshell_function_get_name(const bshell_function *func)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
BSHELL_TYPE_FUNCTION,
|
||||
function_get_name,
|
||||
func);
|
||||
}
|
||||
|
||||
const fx_array *bshell_function_get_positional_parameters(
|
||||
const bshell_function *func)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
BSHELL_TYPE_FUNCTION,
|
||||
function_get_positional_parameters,
|
||||
func);
|
||||
}
|
||||
|
||||
bshell_scriptblock *bshell_function_get_body(bshell_function *func)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
BSHELL_TYPE_FUNCTION,
|
||||
function_get_body,
|
||||
func);
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_function)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_INTERFACE_ENTRY(c_command_type) = "Function";
|
||||
FX_INTERFACE_ENTRY(c_get_callable_name) = get_callable_name;
|
||||
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
|
||||
FX_INTERFACE_ENTRY(c_process_record) = process_record;
|
||||
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_TYPE_CLASS_END(bshell_function)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_function)
|
||||
FX_TYPE_ID(0x041f1918, 0x6155, 0x4cee, 0xbb01, 0xfef2d6aa1bcf);
|
||||
FX_TYPE_NAME("bshell.runtime.function");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND);
|
||||
FX_TYPE_CLASS(bshell_function_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_FINI(fini);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_function_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_function)
|
||||
|
||||
Reference in New Issue
Block a user