Skip to content

Commit 269f9d0

Browse files
committed
Prepared cli for command implementation.
1 parent 9feea7b commit 269f9d0

File tree

3 files changed

+110
-126
lines changed

3 files changed

+110
-126
lines changed

source/cli/metacallcli/include/metacallcli/application.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ class application
8989
*/
9090
void *execute(void *tokens);
9191

92+
/**
93+
* @brief
94+
* Check if a value is an exception or throwable, then prints it.
95+
* The method always destroys the value @v
96+
*
97+
* @param[inout] v
98+
* Value to be checked against and destroyed
99+
*/
100+
void check_for_exception(void *v);
101+
92102
private:
93103
/* -- Private Member Data -- */
94104

source/cli/metacallcli/source/application.cpp

Lines changed: 43 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -38,62 +38,6 @@ static bool exit_condition = true;
3838

3939
/* -- Methods -- */
4040

41-
// void application::print(void *v)
42-
// {
43-
// /* TODO: Delete this, implement command line arguments parser in js */
44-
// if (v == NULL)
45-
// {
46-
// std::cout << "null" << std::endl;
47-
// }
48-
// else
49-
// {
50-
// if (metacall_value_id(v) == METACALL_THROWABLE)
51-
// {
52-
// std::cout << "TODO: Throwable" << std::endl;
53-
// }
54-
// else
55-
// {
56-
// size_t size = 0;
57-
// struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free };
58-
// void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx);
59-
// char *value_str = metacall_serialize(metacall_serial(), v, &size, allocator);
60-
61-
// std::cout << value_str << std::endl;
62-
63-
// metacall_allocator_free(allocator, value_str);
64-
// }
65-
66-
// metacall_value_destroy(v);
67-
// }
68-
// }
69-
70-
// void application::invoke(const char *func, void *args[], size_t size)
71-
// {
72-
// /* TODO: Delete this, implement command line arguments parser in js */
73-
// void *ret = metacallhv_s(plugin_cli_handle, func, args, size);
74-
75-
// if (metacall_value_id(ret) == METACALL_INT)
76-
// {
77-
// int result = metacall_value_to_int(ret);
78-
79-
// if (result != 0)
80-
// {
81-
// std::cout << "Failed to execute '" << func << "' command, return code: " << result;
82-
// }
83-
84-
// metacall_value_destroy(ret);
85-
// }
86-
// else
87-
// {
88-
// print(ret);
89-
// }
90-
91-
// for (size_t it = 0; it < size; ++it)
92-
// {
93-
// metacall_value_destroy(args[it]);
94-
// }
95-
// }
96-
9741
// void application::parameter_iterator::operator()(const char *parameter)
9842
// {
9943
// // TODO: Implement a new plugin for parsing command line options
@@ -177,25 +121,6 @@ application::application(int argc, char *argv[]) :
177121
/* Print MetaCall information */
178122
metacall_print_info();
179123

180-
// TODO: Implement a new plugin for parsing command line options
181-
// TODO: Implement a new plugin for parsing command line options
182-
// TODO: Implement a new plugin for parsing command line options
183-
184-
// /* TODO: This has been updated, review it: */
185-
// /* Parse program arguments if any (e.g metacall (0) a.py (1) b.js (2) c.rb (3)) */
186-
// if (argc > 1)
187-
// {
188-
// parameter_iterator param_it(*this);
189-
190-
// /* TODO: This has been refactored in order to pass the arguments to the runtimes */
191-
// /* Using argv + 2 by now, but this should be deleted in a near future or review the implementation */
192-
193-
// /* Parse program parameters */
194-
// std::for_each(&argv[1], argv + /*argc*/ 2, param_it);
195-
196-
// return;
197-
// }
198-
199124
/* Initialize REPL plugins */
200125
if (!load_path("repl", &plugin_repl_handle))
201126
{
@@ -205,6 +130,34 @@ application::application(int argc, char *argv[]) :
205130
return;
206131
}
207132

133+
if (argc == 1)
134+
{
135+
void *ret = metacallhv_s(plugin_repl_handle, "initialize", metacall_null_args, 0);
136+
137+
check_for_exception(ret);
138+
}
139+
else
140+
{
141+
void *arguments_parse_func = metacall_handle_function(plugin_repl_handle, "arguments_parse");
142+
143+
if (arguments_parse_func == NULL)
144+
{
145+
/* Use fallback parser, it can execute files but does not support command line arguments as options (i.e: -h, --help) */
146+
/* Parse program arguments if any (e.g metacall (0) a.py (1) b.js (2) c.rb (3)) */
147+
148+
// TODO
149+
exit_condition = true;
150+
return;
151+
}
152+
else
153+
{
154+
/* TODO: Implement a new plugin for parsing command line options */
155+
std::cout << "TODO: CLI Arguments Parser Plugin is not implemented yet" << std::endl;
156+
exit_condition = true;
157+
return;
158+
}
159+
}
160+
208161
/* Initialize CLI plugins */
209162
if (load_path("cli", &plugin_cli_handle))
210163
{
@@ -383,8 +336,7 @@ void application::run()
383336
/* Invoke next iteration of the REPL */
384337
void *ret = metacallfv_s(metacall_value_to_function(results[1]), args, 2);
385338

386-
/* TODO: Do something with ret? */
387-
metacall_value_destroy(ret);
339+
check_for_exception(ret);
388340

389341
metacall_value_destroy(args[0]);
390342
metacall_value_destroy(args[1]);
@@ -398,7 +350,7 @@ void application::run()
398350
{
399351
void *ret = metacallhv_s(plugin_repl_handle, "close", metacall_null_args, 0);
400352

401-
metacall_value_destroy(ret);
353+
check_for_exception(ret);
402354
}
403355
}
404356

@@ -418,3 +370,16 @@ void *application::execute(void *tokens)
418370
return metacallhv_s(plugin_cli_handle, metacall_value_to_string(key), &tokens_array[1], size - 1);
419371
}
420372
}
373+
374+
void application::check_for_exception(void *v)
375+
{
376+
struct metacall_exception_type ex;
377+
378+
if (metacall_error_from_value(v, &ex) == 0)
379+
{
380+
std::cout << "Exception: " << ex.message << std::endl
381+
<< ex.stacktrace << std::endl;
382+
}
383+
384+
metacall_value_destroy(v);
385+
}

source/cli/plugins/cli_repl_plugin/source/cli_repl_plugin.js

Lines changed: 57 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -27,62 +27,67 @@ const new_repl_promise = () => {
2727
return { resolve: promise_resolve, reject: promise_reject, wait };
2828
}
2929

30-
let repl_promise = [new_repl_promise()];
31-
32-
/* Show welcome message */
33-
console.log('Welcome to Tijuana, tequila, sexo & marijuana.');
34-
35-
/* Start REPL */
36-
const repl = r.start({
37-
prompt: '\u03BB ',
38-
useGlobal: false,
39-
ignoreUndefined: true,
40-
preview: true,
41-
eval: evaluator,
42-
completer: completer
43-
});
44-
45-
function evaluator(cmd, context, file, cb) {
46-
if (repl_promise === null) {
47-
cb(new Error('Invalid REPL Promise'), null);
48-
}
30+
let repl_promise = null;
31+
let repl = null;
32+
33+
function initialize() {
34+
repl_promise = [new_repl_promise()];
35+
36+
/* Show welcome message */
37+
console.log('Welcome to Tijuana, tequila, sexo & marijuana.');
38+
39+
/* Start REPL */
40+
repl = r.start({
41+
prompt: '\u03BB ',
42+
useGlobal: false,
43+
ignoreUndefined: true,
44+
preview: true,
45+
eval: evaluator,
46+
completer: completer
47+
});
4948

50-
if (repl_promise.length === 0) {
51-
repl_promise.push(new_repl_promise());
52-
}
49+
function evaluator(cmd, context, file, cb) {
50+
if (repl_promise === null) {
51+
cb(new Error('Invalid REPL Promise'), null);
52+
}
5353

54-
const promise = repl_promise[repl_promise.length - 1];
54+
if (repl_promise.length === 0) {
55+
repl_promise.push(new_repl_promise());
56+
}
57+
58+
const promise = repl_promise[repl_promise.length - 1];
59+
60+
try {
61+
const result = command_parse(cmd.trim());
62+
promise.resolve([result, cb]);
63+
} catch (e) {
64+
promise.resolve([e, cb]);
65+
}
5566

56-
try {
57-
const result = command_parse(cmd.trim());
58-
promise.resolve([result, cb]);
59-
} catch (e) {
60-
promise.resolve([e, cb]);
67+
repl_promise.push(new_repl_promise());
6168
}
6269

63-
repl_promise.push(new_repl_promise());
64-
}
70+
function completer(line) {
71+
const completions = command_completer();
72+
const hits = completions.filter(c => c.startsWith(line));
73+
return [hits.length ? hits : completions, line];
74+
}
6575

66-
function completer(line) {
67-
const completions = command_completer();
68-
const hits = completions.filter(c => c.startsWith(line));
69-
return [hits.length ? hits : completions, line];
70-
}
76+
/* Clear context and commands */
77+
repl.context = vm.createContext({});
78+
repl.commands = {};
7179

72-
/* Clear context and commands */
73-
repl.context = vm.createContext({});
74-
repl.commands = {};
80+
/* On close event reject the repl promise */
81+
repl.on('close', () => {
82+
if (repl_promise !== null) {
83+
if (repl_promise.length === 1) {
84+
repl_promise[0].reject();
85+
}
7586

76-
/* On close event reject the repl promise */
77-
repl.on('close', () => {
78-
if (repl_promise !== null) {
79-
if (repl_promise.length === 1) {
80-
repl_promise[0].reject();
87+
repl_promise.pop();
8188
}
82-
83-
repl_promise.pop();
84-
}
85-
});
89+
});
90+
}
8691

8792
/* Usage:
8893
* evaluate().then(data => {
@@ -109,6 +114,7 @@ const evaluate = async () => {
109114
};
110115

111116
module.exports = {
117+
initialize,
112118
evaluate,
113119
/* This function is exported so it can be called from other plugins:
114120
*
@@ -136,7 +142,10 @@ module.exports = {
136142
command_register,
137143

138144
close: () => {
145+
if (repl) {
146+
repl.close();
147+
repl = null;
148+
}
139149
repl_promise = null;
140-
repl.close();
141150
}
142151
};

0 commit comments

Comments
 (0)