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;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;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