y_tab解释程序中,虽然有了用户自定义函数的功能,能够按照值传递规则传递参数,但是仍然不能传递引用。传递引用比较复杂,并且最终会在细粒度上对变量引用的解释产生影响。y_tab不打算实现这个功能。但是可以增加一个全局的,名字叫output的特殊数组,让每个用户自定义函数自动拥有这个数组,从而获得函数之间共享全局数据的功能。
这只要在初始化时,在全局和局部符号表中插入一个名叫output的数组,并且从不清除它。
struct abpvector {
VALUE_TYPE *vector;
VALUE_TYPE **abp;
} output;
...
void init_whatever()
{
int i;
int k;
for(k=0; k<2; k++) {
memset(&symtab_compile[k],0,sizeof(struct symtab));
memset(&funxat_compile[k],0,sizeof(struct funxat));
for(i=0; i<MAXARRAY; i++) {
symtab_compile[k].avartab[i] =
symtab_compile[k].array[i];
}
strcpy(symtab_compile[k].arraytab[0].name,"output");
symtab_compile[k].arraycount=1;
funxat_compile[k].avars=1;
symtab_compile[k].used_const0=0;
funxat_compile[k].strtab = symtab_compile[k].strtab;
funxat_compile[k].consttab = symtab_compile[k].consttab;
funxat_compile[k].labeltab = symtab_compile[k].gototab;
funxat_compile[k].consttab[0].type = 0;
funxat_compile[k].consttab[0].u.value = 1;
funxat_compile[k].constcount = 1;
funxat_compile[k].labelcount = 0;
}
tmpnamecount=0;
dmc=0;
top=0;
swc= -1;
funxvt_main = &stk->e[0];
funxvt_main->func = &funxat_compile[0];
funxvt_main->bp = symtab_compile[0].var;
funxvt_main->abp = symtab_compile[0].avartab;
output.vector = funxvt_main->abp[0];
output.abp = &output.vector;
}
上面,strcpy()的这几句,在符号表中增加"output"符号,最后output的2句,给这个数组分配固定空间。
此外,还要在调用用户自定义函数分配空间时,及用户自定义函数返回回收分配空间时,跳过这个output数组。
void alloc_context(struct funxat *f)
{
struct funxvt *context;
struct segment *seg;
int i;
++top;
if (top >= SEGLEN) {
seg = (struct segment *)Malloc(sizeof(struct segment));
seg->wrap = stk;
stk = seg;
top =0;
}
context = &stk->e[top];
context->func = f;
if (f->vars) {
context->bp = (VALUE_TYPE *)Malloc(sizeof(VALUE_TYPE)*f->vars);
memset(context->bp,0, sizeof(VALUE_TYPE)*f->vars);
//........ .......... .... ............... ..
}
else context->bp = NULL;
if (f->avars>1) {
context->abp = (VALUE_TYPE**)Malloc(
sizeof(VALUE_TYPE*) * f->avars);
context->abp[0] = output.vector;
for(i=1; i<f->avars; i++) {
context->abp[i] =
(VALUE_TYPE *)Malloc(sizeof(VALUE_TYPE)*MAXCELL);
memset(context->abp[i],0,sizeof(VALUE_TYPE)*MAXCELL);
}
}
else context->abp = output.abp;
}
void free_context()
{
struct funxvt *context;
struct funxat *f;
struct segment *seg;
int i,j;
if (top == 0 && stk->wrap==NULL) {
printf("runtime stack corrupt!\n");
return;
}
context = &stk->e[top];
f = context->func;
//............. .... ....... .. ......... .........
if (context->bp) {
for(i=0; i<f->vars; i++) context->bp[i]=dummy_value;
free(context->bp);
context->bp =NULL;
}
if (f->avars>1) {
for(i=1; i<f->avars; i++) {
for(j=0; j<MAXCELL; j++) context->abp[i][j]=dummy_value;
free(context->abp[i]);
}
free(context->abp);
context->abp= NULL;
}
else context->abp= NULL;
--top;
if (top <0) {
seg = stk->wrap;
free(stk);
stk=seg;
top = SEGLEN-1;
}
}
当然,在清理符号表时,也跳过这个符号。
ss:
| ss ls { int exception=0;
execute_e_ls((struct node*)$2, 0, &exception);
free_compile(&funxat_compile[dmc]); }
| ss error {error_state=1;} '\n' {
if (dmc == DM_FOR_LOCAL) {
free_compile(&funxat_compile[dmc]);
symtab_compile[dmc].varcount=0;
symtab_compile[dmc].arraycount=1;
symtab_compile[dmc].used_const0=0;
funxat_compile[dmc].avars=1;
while(swc>=0) popswitch();
dmc = DM_FOR_GLOBAL;
}
free_compile(&funxat_compile[dmc]);
error_state = 0;
}
| ss defs {
free_compile(&funxat_compile[dmc]);
symtab_compile[dmc].varcount=0;
symtab_compile[dmc].arraycount=1;
symtab_compile[dmc].used_const0=0;
funxat_compile[dmc].avars=1;
dmc = DM_FOR_GLOBAL;
}
;
现在编译,运行,来试一试快速排序例子:
output[] = {17,13,31, 18, 19, 112, 14, 125, 11,111,
7,3,1, 8, 9, 12, 4, 25, 1,21};
func patition(left, right)
{
key = left;
while (left < right)
{
while (left < right && output[right] >= output[key])
right--;
while (left < right && output[left] <= output[key])
left++;
x=output[right];
output[right]=output[left];
output[left]=x;
}
mid = left;
x=output[mid];
output[mid]=output[key];
output[key]=x;
return mid;
}
func QuickSort(left, right)
{
mid = patition(left,right);
if (left < mid - 1) QuickSort(left, mid-1);
if (mid + 1 < right) QuickSort(mid+1, right);
}
for(i=0; output[i]; i++);
n=i;
QuickSort(0, n-1);
i=0;
while(i<n) print output[i++], "\b";
print "END";
这里在全局,patition()函数,QuickSort()函数之间共享了output[]数组的数据。
运行结果:
saving patition...used func[0].
saving QuickSort...used func[1].
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
再跑个斐波拉挈查找看看:
func fibfind(k, n)
{
prev=1;
fn= 1;
while(fn <n) {
fn+=prev;
prev= fn-prev;
}
part_nonfib:
if (p==n) return -1;
while (fn>n-p) {
prev=fn-prev;
fn-=prev;
}
p+=fn-1;
if(output[p]==k) return p;
if(output[p++] <k) goto part_nonfib;
p-=fn;
while (fn>1) {
prev= fn-prev;
fn-=prev;
p+=fn-1;
if (output[p]==k) return p;
if (output[p++]>k) {
p-=fn;
}
}
if (output[p]==k) return p;
return -1;
}
运行结果:
saving fibfind...used func[2].
n=20;
k=17;
print fibfind(k, n);
11