// test: echo -e 'dec (2)\ndisp' | calc.exe | grep -q "storage: 0 -1 0 0 0 0 0 0 0 0"
// test: echo -e 'sto (3, pi)\nclr\ndisp' | calc.exe | grep -q "storage: 0 0 0 0 0 0 0 0 0 0"
// test: echo -e 'mem (3)\nclr\nquit' | calc.exe -v 3 | grep -q Clear
-// test: echo -e 'prog (2, 2, {rcl (2) - rcl (1)})\nprog (1, 1, {cos (rcl (1)^2)})\ncall (1, pi/6)\nprog (2, 1, {rcl (1) * 3})\ncall (2, 1, 2)\nls' | calc.exe
-// test: echo -e 'prog (1, 2, {rcl (2) - rcl (1)})\ncall (1, 2, 3)\nls\nedit (1)\nprog (1, 2, {rcl (2) + rcl (1)})\nedit (1)\ndel (1)\nquit' | calc.exe -v 3 | grep -q bye
-// test: echo -e 'prog (2, 2, {rcl (2) - rcl (1)})\nprog (3, 1, cos(rcl (1) * pi / 3))\ncall (1, 2, 3)\nls\nedit (1)\ndel (1)\n\ndel (2)\ncall (2, 1, 4)' | calc.exe | grep -c error | xargs test 4 =
+// test: echo -e 'prog (2, {arg (2) - arg (1)})\nprog (1, {cos (arg (1)^2)})\ncall (1, pi/6)\nprog (2, {arg (1) * 3})\ncall (2, 1, 2)\nls' | calc.exe
+// test: echo -e 'prog (1, {arg (2) - arg (1)})\ncall (1, 2, 3)\nls\nedit (1)\nprog (1, {arg (2) + arg (1)})\nedit (1)\ndel (1)\nquit' | calc.exe -v 3 | grep -q bye
+// test: echo -e 'prog (2, {arg (2) - arg (1)})\nprog (3, cos(arg (1) * pi / 3))\ncall (1, 2, 3)\nls\nedit (1)\ndel (1)\n\ndel (2)\ncall (2, 1, 4)' | calc.exe | grep -c error | xargs test 4 =
// test: echo -e 'erf (1)\nerfc (1)\nquit' | calc.exe -v 3 | grep -q bye
// test: echo -e 'erf ()\nerfc ()' | calc.exe | grep -c error | xargs test 2 =
// test: echo -e 'set (1, 2, 3, 3.11, pi, 4)\nget (4)' | calc.exe | grep '=> 3.11'
// test: echo -e 'set (0, -1)\nset (1, 2, 3, 3.11, pi, 4)\nlen' | calc.exe | grep '=> 6'
// test: echo -e 'set (1, 2)\npop\npush (3)\nput (5, -1)\nlen\nshow\nget (3)\nquit' | calc.exe -n -v 3 | grep -q bye
// test: echo -e 'put\nget\nget (1)\npop\nput (0)' | calc.exe | grep -c 'error' | xargs test 5 =
-// test: echo -e 'prog (1, 1, {set (1, 2), push (rcl (1)), show})\ncall (1, 10)\nprog (1, 1, cos (rcl (1)))\ncall (1, pi / 2)' | calc.exe -n | grep -q 'stack: 1 2 10'
-// test: echo -e 'prog (1, 1, {set (1, 2), push (rcl (1)), show});\ncall (1, 10);\nshow\ndel (1)' | calc.exe | grep -q 'stack:$'
-// test: echo -e 'prog (1, 1, {set (1, 2), push (rcl (1)), show});\ncall (1, 10);\nlen' | calc.exe | grep -q '=> 0'
+// test: echo -e 'prog (1, {set (1, 2), push (arg (1)), show})\ncall (1, 10)\nprog (1, cos (arg (1)))\ncall (1, pi / 2)' | calc.exe -n | grep -q 'stack: 1 2 10'
+// test: echo -e 'prog (1, {set (1, 2), push (arg (1)), show});\ncall (1, 10);\nshow\ndel (1)' | calc.exe | grep -q 'stack:$'
+// test: echo -e 'prog (1, {set (1, 2), push (arg (1)), show});\ncall (1, 10);\nlen' | calc.exe | grep -q '=> 0'
+// test: echo -e 'prog (1, {mem (2), sto (1, arg (1) - rcl (1) / 2)})\ncall (1, 1)\ncall (1, 2)\ncall (1, 3)' | calc.exe | grep -q '=> 2.25'
// Gauss sequence
// test: echo -e '{sto (1, 0), sto (10, 0), while (inc (10) < 100, {sto (1, rcl (1) + rcl (10)), print (rcl (1))})};' | calc.exe | grep -q '=> 5050'
int storage_size = -1;
double *storage = NULL;
+int argument_size = 0;
+double *argument = NULL;
+
int stack_size = 0;
double *stack = NULL;
{ "|", Or, 2, 1, -2}
};
-#define NB_FUNCTIONS 41
+#define NB_FUNCTIONS 42
keyword_t functions[NB_FUNCTIONS] = {
{ "sqrt", Sqr, 1, 4, 5},
{ "pow", Pow, 2, 3, 5},
{ "inc", Inc, 1, 3, 5},
{ "dec", Dec, 1, 3, 5},
{ "disp", Disp, 0, 4, 9},
- { "mem", Mem, 1, 3, 9},
+ { "mem", Mem, 1, 3, 5},
{ "clr", Clear, 0, 3, 9},
{ "quit", Quit, 0, 4, 9},
{ "help", Help, 0, 4, 9},
{ "cond", Cond, 3, 4, 5},
{ "while", While, 2, 5, 5},
{ "print", Print, 1, 5, 5},
- { "prog", Prog, 3, 4, 9},
+ { "prog", Prog, 2, 4, 9},
+ { "arg", Arg, 1, 3, 5},
{ "call", Call, MAX_ARGS, 4, 5},
{ "ls", List, 0, 2, 9},
{ "edit", Edit, 1, 4, 9},
delelement (root);
return ERROR_OP;
}
- element_t *newprog = newelement (Code, root->nbops + 1, 5);
+ element_t *newcode = newelement (Code, root->nbops + 1, 5);
for (i = 0; i < root->nbops; i++) {
- newprog->ops[i] = root->ops[i];
+ newcode->ops[i] = root->ops[i];
root->ops[i] = NULL;
}
- newprog->ops[root->nbops] = new;
+ newcode->ops[root->nbops] = new;
delelement (root);
- root = newprog;
+ root = newcode;
} while (*str == ',');
if (*str != '}') {
case Code: func = "Code"; break;
case Print: func = "Print"; break;
case Prog: func = "Program"; break;
+ case Arg: func = "Argument"; break;
case Call: func = "Call"; break;
case List: func = "List"; break;
case Edit: func = "Edit"; break;
/* program function */
-void prog (int id, int nbmems, element_t *root)
+void prog (int id, element_t *root)
{
int i, n = -1;
/* set program */
(programs + n)->id = id;
(programs + n)->answer = 0;
- (programs + n)->storage = (double *) callocordie (nbmems, sizeof (double));
- (programs + n)->storage_size = nbmems;
+ (programs + n)->storage = NULL;
+ (programs + n)->storage_size = 0;
(programs + n)->stack = NULL;
(programs + n)->stack_size = 0;
(programs + n)->root = dupelement (root);
}
-double call (int id, int nbops, element_t **ops)
+double arg (int id)
+{
+ double ret = 0;
+ if ((id <= 0) || (id > argument_size)) {
+ VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size));
+ } else {
+ ret = argument[id - 1];
+ }
+ return ret;
+}
+
+double call (int id, int nbargs, element_t **args)
{
workspace_t tmp = {0};
- int i, n = -1;
+ int i, l, n = -1;
double ret = 0;
if (programs) {
/* store context */
tmp.answer = answer;
+ tmp.argument = argument;
+ tmp.argument_size = argument_size;
tmp.storage = storage;
tmp.storage_size = storage_size;
tmp.stack = stack;
answer = 0;
storage = (programs + n)->storage;
storage_size = (programs + n)->storage_size;
+ argument = NULL;
+ argument_size = 0;
stack = (programs + n)->stack;
stack_size = (programs + n)->stack_size;
- if (nbops > storage_size) {
- double *tmp = (double *) callocordie (nbops, sizeof (double));
- memcpy (tmp, storage, storage_size * sizeof (double));
- free (storage);
- (programs + n)->storage = storage = tmp;
- (programs + n)->storage_size = storage_size = nbops;
- }
- for (i = 0; i < nbops; i++) {
- double val = evaluate_element (ops[i], 0);
- store (i + 1, val);
+ if (nbargs > 0) {
+ argument = (double *) callocordie (nbargs, sizeof (double));
+ for (i = 0, l = 0; i < nbargs; l++) {
+ if (args[l]) {
+ argument[i++] = evaluate_element (args[l], 0);
+ }
+ }
+ argument_size = nbargs;
}
/* evaluate program */
(programs + n)->answer = answer;
(programs + n)->storage = storage;
(programs + n)->storage_size = storage_size;
+ if (argument) {
+ free (argument);
+ }
(programs + n)->stack = stack;
(programs + n)->stack_size = stack_size;
answer = tmp.answer;
storage = tmp.storage;
storage_size = tmp.storage_size;
+ argument = tmp.argument;
+ argument_size = tmp.argument_size;
stack = tmp.stack;
stack_size = tmp.stack_size;
fprintf (stdout, "control flow prim.:");
fprintf (stdout, " cond print while {} ;\n");
fprintf (stdout, "program management:");
- fprintf (stdout, " call del edit ls prog\n");
+ fprintf (stdout, " arg call del edit ls prog\n");
fprintf (stdout, "stack management:");
fprintf (stdout, " get len pop push put set show\n");
fprintf (stdout, "control management:");
case Lt:
case And:
case Or:
- case Prog:
if (root->ops[1]) {
op1 = evaluate_element (root->ops[1], nextmask);
} else if (root->func != Store) {
case Not:
case Mem:
case Cond:
+ case Prog:
+ case Arg:
case Call:
case Edit:
case Del:
case Code: return execute_code (root->ops, root->nbops);
case Print: return print (op0);
case Prog:
- prog ((int)op0, (int)op1, root->ops[2]);
+ prog ((int)op0, root->ops[1]);
savestring ((int)op0, root->string);
break;
+ case Arg: return arg ((int)op0);
case Call:
for (i = 1, nb =0; i < root->nbops; i++) {
if (root->ops[i]) {