Skip to content

Commit 2844d7d

Browse files
committed
COMMON: Allow modules to return objects with methods that take arguments
1 parent c53736b commit 2844d7d

File tree

11 files changed

+202
-171
lines changed

11 files changed

+202
-171
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2024-01-06 (12.27)
2+
COMMON: Allow modules to return objects with methods that take arguments
3+
14
2023-08-27 (12.27)
25
COMMON: Fix parameter number error when calling a unit sub/func
36
COMMON: Show a runtime error if a module calls exit()

src/common/blib.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "common/fmt.h"
1313
#include "common/keymap.h"
1414
#include "common/messages.h"
15+
#include "common/plugins.h"
1516

1617
#define STR_INIT_SIZE 256
1718
#define PKG_INIT_SIZE 5
@@ -2881,12 +2882,21 @@ void cmd_call_vfunc() {
28812882
rt_raise(ERR_NO_FUNC);
28822883
}
28832884
} else {
2885+
slib_par_t *ptable;
2886+
int pcount;
28842887
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
2885-
code_skipnext();
2888+
ptable = (slib_par_t *)malloc(sizeof(slib_par_t) * MAX_PARAMS);
2889+
pcount = plugin_build_ptable(ptable, MAX_PARAMS);
2890+
} else {
2891+
ptable = NULL;
2892+
pcount = 0;
28862893
}
2887-
v_func->v.fn.cb(map, NULL);
2888-
if (code_peek() == kwTYPE_LEVEL_END) {
2889-
code_skipnext();
2894+
if (!prog_error) {
2895+
v_func->v.fn.cb(map, pcount, ptable, NULL);
2896+
}
2897+
if (ptable) {
2898+
plugin_free_ptable(ptable, pcount);
2899+
free(ptable);
28902900
}
28912901
}
28922902
}

src/common/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ static inline void eval_var(var_t *r, var_t *var_p) {
786786
v_set(r, var_p);
787787
break;
788788
case V_FUNC:
789-
var_p->v.fn.cb(var_p, r);
789+
var_p->v.fn.cb(var_p, 0, NULL, r);
790790
break;
791791
case V_NIL:
792792
r->type = V_NIL;

src/common/plugins.c

Lines changed: 71 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -358,80 +358,6 @@ static void slib_import_routines(slib_t *lib, int comp) {
358358
}
359359
}
360360

361-
//
362-
// build parameter table
363-
//
364-
static int slib_build_ptable(slib_par_t *ptable) {
365-
int pcount = 0;
366-
var_t *arg;
367-
bcip_t ofs;
368-
369-
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
370-
code_skipnext();
371-
byte ready = 0;
372-
do {
373-
byte code = code_peek();
374-
switch (code) {
375-
case kwTYPE_EOC:
376-
code_skipnext();
377-
break;
378-
case kwTYPE_SEP:
379-
code_skipsep();
380-
break;
381-
case kwTYPE_LEVEL_END:
382-
ready = 1;
383-
break;
384-
case kwTYPE_VAR:
385-
// variable
386-
ofs = prog_ip;
387-
if (code_isvar()) {
388-
// push parameter
389-
ptable[pcount].var_p = code_getvarptr();
390-
ptable[pcount].byref = 1;
391-
pcount++;
392-
break;
393-
}
394-
395-
// restore IP
396-
prog_ip = ofs;
397-
// no 'break' here
398-
default:
399-
// default --- expression (BYVAL ONLY)
400-
arg = v_new();
401-
eval(arg);
402-
if (!prog_error) {
403-
// push parameter
404-
ptable[pcount].var_p = arg;
405-
ptable[pcount].byref = 0;
406-
pcount++;
407-
} else {
408-
v_free(arg);
409-
v_detach(arg);
410-
return pcount;
411-
}
412-
}
413-
if (pcount == MAX_PARAM) {
414-
err_parm_limit(MAX_PARAM);
415-
}
416-
} while (!ready && !prog_error);
417-
// kwTYPE_LEVEL_END
418-
code_skipnext();
419-
}
420-
return pcount;
421-
}
422-
423-
//
424-
// free parameter table
425-
//
426-
static void slib_free_ptable(slib_par_t *ptable, int pcount) {
427-
for (int i = 0; i < pcount; i++) {
428-
if (ptable[i].byref == 0) {
429-
v_free(ptable[i].var_p);
430-
v_detach(ptable[i].var_p);
431-
}
432-
}
433-
}
434-
435361
//
436362
// execute a function or procedure
437363
//
@@ -440,13 +366,13 @@ static int slib_exec(slib_t *lib, var_t *ret, int index, int proc) {
440366
int pcount;
441367
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
442368
ptable = (slib_par_t *)malloc(sizeof(slib_par_t) * MAX_PARAM);
443-
pcount = slib_build_ptable(ptable);
369+
pcount = plugin_build_ptable(ptable, MAX_PARAM);
444370
} else {
445371
ptable = NULL;
446372
pcount = 0;
447373
}
448374
if (prog_error) {
449-
slib_free_ptable(ptable, pcount);
375+
plugin_free_ptable(ptable, pcount);
450376
free(ptable);
451377
return 0;
452378
}
@@ -470,7 +396,7 @@ static int slib_exec(slib_t *lib, var_t *ret, int index, int proc) {
470396

471397
// clean-up
472398
if (ptable) {
473-
slib_free_ptable(ptable, pcount);
399+
plugin_free_ptable(ptable, pcount);
474400
free(ptable);
475401
}
476402

@@ -643,3 +569,71 @@ int plugin_funcexec(int lib_id, int index, var_t *ret) { return -1; }
643569
void plugin_free(int lib_id, int cls_id, int id) {}
644570
void plugin_close() {}
645571
#endif
572+
573+
int plugin_build_ptable(slib_par_t *ptable, int size) {
574+
int pcount = 0;
575+
var_t *arg;
576+
bcip_t ofs;
577+
578+
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
579+
code_skipnext();
580+
byte ready = 0;
581+
do {
582+
byte code = code_peek();
583+
switch (code) {
584+
case kwTYPE_EOC:
585+
code_skipnext();
586+
break;
587+
case kwTYPE_SEP:
588+
code_skipsep();
589+
break;
590+
case kwTYPE_LEVEL_END:
591+
ready = 1;
592+
break;
593+
case kwTYPE_VAR:
594+
// variable
595+
ofs = prog_ip;
596+
if (code_isvar()) {
597+
// push parameter
598+
ptable[pcount].var_p = code_getvarptr();
599+
ptable[pcount].byref = 1;
600+
pcount++;
601+
break;
602+
}
603+
604+
// restore IP
605+
prog_ip = ofs;
606+
// no 'break' here
607+
default:
608+
// default --- expression (BYVAL ONLY)
609+
arg = v_new();
610+
eval(arg);
611+
if (!prog_error) {
612+
// push parameter
613+
ptable[pcount].var_p = arg;
614+
ptable[pcount].byref = 0;
615+
pcount++;
616+
} else {
617+
v_free(arg);
618+
v_detach(arg);
619+
return pcount;
620+
}
621+
}
622+
if (pcount == size) {
623+
err_parm_limit(size);
624+
}
625+
} while (!ready && !prog_error);
626+
// kwTYPE_LEVEL_END
627+
code_skipnext();
628+
}
629+
return pcount;
630+
}
631+
632+
void plugin_free_ptable(slib_par_t *ptable, int pcount) {
633+
for (int i = 0; i < pcount; i++) {
634+
if (ptable[i].byref == 0) {
635+
v_free(ptable[i].var_p);
636+
v_detach(ptable[i].var_p);
637+
}
638+
}
639+
}

src/common/plugins.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ int plugin_get_kid(int lib_id, const char *keyword);
4444
// returns the function pointer for the given function name
4545
//
4646
void *plugin_get_func(const char *name);
47-
47+
4848
//
4949
// executes the plugin procedure at the given index
5050
//
@@ -65,6 +65,16 @@ void plugin_free(int lib_id, int cls_id, int id);
6565
//
6666
void plugin_close();
6767

68+
//
69+
// build parameter table
70+
//
71+
int plugin_build_ptable(slib_par_t *ptable, int size);
72+
73+
//
74+
// free parameter table
75+
//
76+
void plugin_free_ptable(slib_par_t *ptable, int pcount);
77+
6878
#if defined(__cplusplus)
6979
}
7080
#endif

src/include/module.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@
1616
extern "C" {
1717
#endif
1818

19-
typedef struct {
20-
// the parameter
21-
var_t *var_p;
22-
23-
// whether the parameter can be used by reference
24-
uint8_t byref;
25-
} slib_par_t;
26-
2719
/**
2820
* @ingroup modstd
2921
*

src/include/var.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@ extern "C" {
4747
#endif
4848

4949
struct var_s;
50-
typedef void (*method) (struct var_s *self, struct var_s *retval);
50+
51+
typedef struct {
52+
// the parameter
53+
struct var_s *var_p;
54+
55+
// whether the parameter can be used by reference
56+
uint8_t byref;
57+
} slib_par_t;
58+
59+
// object method signature
60+
typedef void (*method) (struct var_s *self, int param_count, slib_par_t *params, struct var_s *retval);
5161

5262
typedef struct var_s {
5363
union {

src/platform/console/image.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,15 @@ ImageBuffer *load_xpm_image(char **data) {
245245
//
246246
// png.clip(10, 10, 10, 10)
247247
//
248-
void cmd_image_clip(var_s *self, var_s *) {
249-
var_int_t left, top, right, bottom;
248+
void cmd_image_clip(var_s *self, int param_count, slib_par_t *params, var_s *) {
250249
ImageBuffer *image = load_image(self);
251-
if (par_massget("iiii", &left, &top, &right, &bottom) == 4) {
250+
if (param_count != 4) {
251+
err_parm_num(param_count, 4);
252+
} else {
253+
var_int_t left = v_getint(params[0].var_p);
254+
var_int_t top = v_getint(params[1].var_p);
255+
var_int_t right = v_getint(params[2].var_p);
256+
var_int_t bottom = v_getint(params[3].var_p);
252257
int w = image->_width - (right + left);
253258
int h = image->_height - (bottom + top);
254259
int size = w * h * 4;
@@ -277,8 +282,6 @@ void cmd_image_clip(var_s *self, var_s *) {
277282
map_set_int(self, IMG_WIDTH, w);
278283
map_set_int(self, IMG_HEIGHT, h);
279284
}
280-
} else {
281-
err_throw(ERR_PARAM);
282285
}
283286
}
284287

@@ -290,7 +293,7 @@ void cmd_image_clip(var_s *self, var_s *) {
290293
// end
291294
// png.filter(use colorToAlpha(x))
292295
//
293-
void cmd_image_filter(var_s *self, var_s *) {
296+
void cmd_image_filter(var_s *self, int param_count, slib_par_t *params, var_s *) {
294297
ImageBuffer *image_buffer = load_image(self);
295298
if (code_peek() == kwUSE && image_buffer != nullptr) {
296299
code_skipnext();
@@ -326,19 +329,22 @@ void cmd_image_filter(var_s *self, var_s *) {
326329
// png2 = image(w, h)
327330
// png2.paste(png1, 0, 0)
328331
//
329-
void cmd_image_paste(var_s *self, var_s *) {
330-
var_int_t x, y;
331-
var_t *var;
332+
void cmd_image_paste(var_s *self, int param_count, slib_par_t *params, var_s *) {
332333
ImageBuffer *image = load_image(self);
333-
int count = par_massget("Piiii", &var, &x, &y);
334-
if (image != nullptr && (count == 1 || count == 3)) {
334+
if (image != nullptr && (param_count == 1 || param_count == 3)) {
335+
var_t *var = params[0].var_p;
335336
ImageBuffer *srcImage = load_image(var);
336337
if (srcImage == nullptr) {
337338
err_throw(ERR_PARAM);
338339
} else {
340+
var_int_t x;
341+
var_int_t y;
339342
if (count == 1) {
340343
x = 0;
341344
y = 0;
345+
} else {
346+
x = v_getint(params[1].var_p);
347+
y = v_getint(params[2].var_p);
342348
}
343349
int dw = image->_width;
344350
int dh = image->_height;
@@ -370,7 +376,7 @@ void cmd_image_paste(var_s *self, var_s *) {
370376
// png.save("horse1.png")
371377
// png.save(#1)
372378
//
373-
void cmd_image_save(var_s *self, var_s *) {
379+
void cmd_image_save(var_s *self, int param_count, slib_par_t *params, var_s *) {
374380
ImageBuffer *image = load_image(self);
375381
dev_file_t *filep = nullptr;
376382
byte code = code_peek();

src/ui/form.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,29 +116,20 @@ void FormLink::clicked(int x, int y, bool pressed) {
116116
}
117117
}
118118

119-
void cmd_form_close(var_s *self, var_s *) {
119+
void cmd_form_close(var_s *self, int param_count, slib_par_t *params, var_s *) {
120120
g_system->getOutput()->removeInputs();
121121
g_system->getOutput()->resetScroll();
122-
123-
var_t arg;
124-
v_init(&arg);
125-
eval(&arg);
126-
if (arg.type == V_STR) {
127-
g_system->setLoadBreak(arg.v.p.ptr);
122+
if (param_count == 1 && params[0].var_p->type == V_STR) {
123+
g_system->setLoadBreak(params[0].var_p->v.p.ptr);
128124
}
129-
v_free(&arg);
130125
}
131126

132-
void cmd_form_refresh(var_s *self, var_s *) {
133-
var_t arg;
134-
v_init(&arg);
135-
eval(&arg);
136-
bool setVars = v_getint(&arg) != 0;
137-
v_free(&arg);
127+
void cmd_form_refresh(var_s *self, int param_count, slib_par_t *params, var_s *) {
128+
bool setVars = param_count == 1 && v_getint(params[0].var_p) != 0;
138129
g_system->getOutput()->updateInputs(self, setVars);
139130
}
140131

141-
void cmd_form_do_events(var_s *self, var_s *) {
132+
void cmd_form_do_events(var_s *self, int param_count, slib_par_t *params, var_s *) {
142133
// apply any variable changes onto attached widgets
143134
if (g_system->isRunning()) {
144135
AnsiWidget *out = g_system->getOutput();

0 commit comments

Comments
 (0)