201 lines
5.0 KiB
C
201 lines
5.0 KiB
C
#include <bshell/command/command.h>
|
|
#include <bshell/command/function.h>
|
|
#include <bshell/runtime/pipeline.h>
|
|
#include <bshell/runtime/runtime.h>
|
|
#include <bshell/runtime/scope.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,
|
|
enum bshell_command_position position)
|
|
{
|
|
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_scope_define_variable(
|
|
bshell_runtime_get_current_scope(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)
|