Skip to content

Commit 418617d

Browse files
authored
Merge pull request #203 from chrisws/12_27
Improvements for modules
2 parents f7528be + 222d014 commit 418617d

File tree

9 files changed

+181
-99
lines changed

9 files changed

+181
-99
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: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2881,13 +2881,10 @@ void cmd_call_vfunc() {
28812881
rt_raise(ERR_NO_FUNC);
28822882
}
28832883
} else {
2884-
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
2885-
code_skipnext();
2886-
}
2887-
v_func->v.fn.cb(map, NULL);
2888-
if (code_peek() == kwTYPE_LEVEL_END) {
2889-
code_skipnext();
2890-
}
2884+
var_t result;
2885+
v_init(&result);
2886+
v_eval_func(map, v_func, &result);
2887+
v_free(&result);
28912888
}
28922889
}
28932890

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/common/var.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,5 +800,14 @@ void v_create_func(var_p_t map, const char *name, method cb) {
800800
var_p_t v_func = map_add_var(map, name, 0);
801801
v_func->type = V_FUNC;
802802
v_func->v.fn.cb = cb;
803+
v_func->v.fn.mcb = NULL;
804+
v_func->v.fn.id = 0;
805+
}
806+
807+
void v_create_callback(var_p_t map, const char *name, callback cb) {
808+
var_p_t v_func = map_add_var(map, name, 0);
809+
v_func->type = V_FUNC;
810+
v_func->v.fn.cb = NULL;
811+
v_func->v.fn.mcb = cb;
803812
v_func->v.fn.id = 0;
804813
}

src/common/var_eval.c

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// This program is distributed under the terms of the GPL v2.0 or later
66
// Download the GNU Public License (GPL) from www.gnu.org
77
//
8-
// Copyright(C) 2010-2014 Chris Warren-Smith. [http://tinyurl.com/ja2ss]
8+
// Copyright(C) 2010-2024 Chris Warren-Smith. [http://tinyurl.com/ja2ss]
99

1010
#include "common/sys.h"
1111
#include "common/kw.h"
@@ -14,6 +14,55 @@
1414
#include "common/smbas.h"
1515
#include "common/var.h"
1616
#include "common/var_eval.h"
17+
#include "common/plugins.h"
18+
19+
//
20+
// returns a temporary var that can exist in the calling scope
21+
//
22+
var_p_t v_get_tmp(var_p_t map) {
23+
var_p_t result = map_get(map, MAP_TMP_FIELD);
24+
if (result == NULL) {
25+
result = map_add_var(map, MAP_TMP_FIELD, 0);
26+
}
27+
return result;
28+
}
29+
30+
void v_eval_func(var_p_t self, var_p_t v_func, var_p_t result) {
31+
if (v_func->v.fn.cb != NULL) {
32+
// internal object method
33+
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
34+
code_skipnext();
35+
}
36+
v_func->v.fn.cb(self, NULL);
37+
if (code_peek() == kwTYPE_LEVEL_END) {
38+
code_skipnext();
39+
}
40+
} else {
41+
// module callback
42+
slib_par_t *ptable;
43+
int pcount;
44+
if (code_peek() == kwTYPE_LEVEL_BEGIN) {
45+
ptable = (slib_par_t *)malloc(sizeof(slib_par_t) * MAX_PARAMS);
46+
pcount = plugin_build_ptable(ptable, MAX_PARAMS);
47+
} else {
48+
ptable = NULL;
49+
pcount = 0;
50+
}
51+
if (!prog_error) {
52+
if (!v_func->v.fn.mcb(self, pcount, ptable, result)) {
53+
if (result->type == V_STR) {
54+
err_throw(result->v.p.ptr);
55+
} else {
56+
err_throw("Undefined");
57+
}
58+
}
59+
}
60+
if (ptable) {
61+
plugin_free_ptable(ptable, pcount);
62+
free(ptable);
63+
}
64+
}
65+
}
1766

1867
/**
1968
* Convert multi-dim index to one-dim index
@@ -147,18 +196,18 @@ var_t *code_get_map_element(var_t *map, var_t *field) {
147196
if (udf_rv.type != kwTYPE_RET) {
148197
err_stackmess();
149198
} else {
150-
// result must exist until processed in eval()
151-
var_p_t var = map_get(map, MAP_TMP_FIELD);
152-
if (var == NULL) {
153-
var = map_add_var(map, MAP_TMP_FIELD, 0);
154-
}
199+
var_p_t var = v_get_tmp(map);
155200
v_move(var, udf_rv.x.vdvar.vptr);
156201
v_detach(udf_rv.x.vdvar.vptr);
157202
result = var;
158203
}
159204
}
160205
} else if (field->type == V_ARRAY) {
161206
result = code_getvarptr_arridx(field);
207+
} else if (field->type == V_FUNC) {
208+
result = v_get_tmp(map);
209+
v_init(result);
210+
v_eval_func(map, field, result);
162211
} else {
163212
code_skipnext();
164213
var_t var;

src/common/var_eval.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ int code_isvar(void);
6767
*/
6868
void v_eval_str(var_p_t v);
6969

70+
/**
71+
* @ingroup var
72+
*
73+
* invokes the virtual function
74+
*/
75+
void v_eval_func(var_p_t self, var_p_t v_func, var_p_t result);
76+
7077
#if defined(__cplusplus)
7178
}
7279
#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
*

0 commit comments

Comments
 (0)