前文讨论了Goto到另一个函数内部是可行的。现在只需把细节敲定就行了。
首先是语法。考虑到跟原来的编程习惯尽可能相容,并且容易阅读和记忆,稍微调整了一下语法的顺序。语法是:
f().goto label;
代表一个函数调用,并且在调用时直接跳转到函数的label位置执行。就这点。如果有返回值,直接赋值给一个变量就可以了。
a = f().goto label;
原来打算新开一个fgoto语法节点,考虑到跟原来的fcall语法大同小异。原来的fcall的数据指针没用满。只要增加一个 label数据就行了。
exprfgoto : exprfcall '.' GOTO varplus {
struct sym *sym;
struct node *p;
int s;
p = (struct node*) $1;
sym= (struct sym*) $4;
if (p->left== (struct node*)funccount) {
int s;
p = (struct node*) $1;
sym= (struct sym*) $4;
if (p->left== (struct node*)funccount) {
s = lfind(sym->name, strlen(sym->name));
p->medium = (struct node*)s;
}
else {
s = funxat_compile[dmc].strcount++;
funxat_compile[dmc].strtab[s]
= strdup(sym->name);
p->medium = (struct node*)s;
}
$$=p;
}
;
expr: exprfcall {$$=$1;}
|exprfgoto {$$=$1;}
;
fcall的medium指针空闲。现在用来存储label的索引,或者-1,代表还是原来的fcall。label的索引分两种情况,如果是递归调用自己,存的是本地label表的索引,如果是外部函数,存的是label名称字符串的索引。讲究的可以新开一个外部索引表。这里就不讲究了。
原来只有内部label,函数编译好后,只保留label所对应的语句节点。label名称丢弃。现在label名称还用于外部链接。funxat增加一个labelname表,函数编译好后,跟labeltab一起保存到function数组。
最后就是call了。函数调用时检查这个k值,如果是外部label,则提取label名称字符串,检索label表,找到后重新设置这个索引值。如果没有,抛出异常返回。如果是内部label,编译时已经设置好了,无需操作。
struct exprval e_fcall(int fi, struct node *paras, int k, int *exception)
{
struct funxat *f;
struct node *p;
struct exprval e;
int i;
struct exprval ret;
struct exprval *argtab = NULL;
int recursion;
f = &userfunc[fi];
recursion = (f == stk->e[top].func);
if( k!=-1 && !recursion) {
char *s;
s = stk->e[top].func->strtab[k];
k = fgotofind(f, s, strlen(s));
if (k<0) {
printf("function %s(...) has no label `%s'\n",
f->name, s);
goto exception_out;
}
}
......
}
最后执行原来的函数语句,或者抛出goto,现搜索goto,找到后在那条语句开始执行函数。
.........
if (k == -1)
execute_e_ls(f->syntree, 0, exception);
else {
throw_goto.medium = f->labeltab[k];
execute_e_ls(f->syntree, f->labeltab[k], exception);
}
ret = stk->e[top].ret;
free_context();
f->loop--;
if (f->loop==0) {
f->warning= terminate_loop - (terminate_loop/4);
}
exception_out:
if (argtab) free(argtab);
if (*exception==1) {
}
return ret;
}
就这些了。好了,编译看运行效果了。这是原来的daily()的例子:
func daily(n)
{
while(n>0) {
switch(iday) {
case 0:
case_sunday: print ++i, "Sunday"; iday=1; break;
case 1:
case_Monday: print ++i, "Monday"; iday=2; break;
case 2:
case_tuesday: print ++i, "Tuesday"; iday=3; break;
case 3:
case_wednesday: print ++i, "Wednesday"; iday=4; break;
case 4:
case_thursday: print ++i, "Thursday"; iday=5; break;
case 5:
case_friday: print ++i,"Friday"; iday=6; break;
case 6:
case_saturday: print ++i, "Saturday"; iday=0; break;
}
n--;
}
}
saving daily...used func[0].
daily(15).goto case_friday;
1 Friday
2 Saturday
3 Sunday
4 Monday
5 Tuesday
6 Wednesday
7 Thursday
8 Friday
9 Saturday
10 Sunday
11 Monday
12 Tuesday
13 Wednesday
14 Thursday
15 Friday
和另一个fib()函数例子:
func fib(n)
{
print ":","\b";
goo:
print "fib(", n, ")", "\b";
if(n==1||n==0) return 1; else;
j= fib(n-1).goto goo;
k= fib(n-2).goto goo;
print j+k;
return j+k;
}
saving fib...used func[1].
fib(10).goto goo;
fib( 10 ) fib( 9 ) fib( 8 ) fib( 7 ) fib( 6 ) fib( 5 ) fib( 4 ) fib( 3 ) fib( 2
) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
13
fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
21
fib( 6 ) fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
13
34
fib( 7 ) fib( 6 ) fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
13
fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
21
55
fib( 8 ) fib( 7 ) fib( 6 ) fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 )
2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
13
fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
21
fib( 6 ) fib( 5 ) fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
8
fib( 4 ) fib( 3 ) fib( 2 ) fib( 1 ) fib( 0 ) 2
fib( 1 ) 3
fib( 2 ) fib( 1 ) fib( 0 ) 2
5
13
34
89
[补充]上回说到Sort函数。在这里补充一下。冒泡排序,堆排序,快速排序都集成到一起了。注意快速排序部分在这里是局部递归(你肯定是第一次见到):
func reset()
{
output[] = {17,13,31, 18, 19, 112, 14, 125, 11,111,
7,3,1, 8, 9, 12, 4, 25, 1,21};
}
func printall(n)
{
for(i=0; i<n; i++) print output[i],"\b";
print "END";
}
func Sort(left, right)
{
bubbleSort:
print "Method bubbleSort:";
n = right-left+1;
for (i=0; i<n-1; i++) {
for (k=n-1, j=n-2; j>=i; k=j--) {
if (output[left+j] > output[left+k]) {
t = output[left+j];
output[left+j] = output[left+k];
output[left+k] = t;
}
}
printall(n);
}
goto done;
heapSort:
print "Method heapSort:";
n =right-left+1;;
len=n;
print "Make heap:";
ra = 1;
for(i= n/2-1; i>=0; --i) {
j = i;
goto heap;
ra_r1: ;
}
printall(len);
print "Sort heap:";
ra = 2;
while( --n >0 ) {
j = 0;
p = n;
goto swap;
heap:
p = j;
c = j+j+1;
d = c+1;
if ( c>= n) goto next;
j =c;
if ( d<n && output[left+d] > output[left+c] ) {
j = d;
}
if (output[left+p] < output[left+j] ) {
swap:
t = output[left+j];
output[left+j] = output[left+p];
output[left+p] = t;
goto heap;
}
next:
printall(len);
if (ra==1) goto ra_r1;
}
printall(len);
goto done;
quickSort:
print "Method Quicksort:";
n= right-left+1;
sort:
mid = Sort(left,right).goto patition;
printall(right+1);
if (left < mid - 1) Sort(left, mid-1).goto sort;
if (mid + 1 < right) Sort(mid+1, right).goto sort;
goto done;
patition:
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;
done:
return 0;
}
reset();
n=20;
Sort(0,n-1);
reset();
Sort(0,n-1).goto quickSort;
reset();
Sort(0,n-1).goto heapSort;
运行结果:
saving reset...used func[0].
saving printall...used func[1].
saving Sort...used func[2].
Method bubbleSort:
1 17 13 31 18 19 112 14 125 11 111 7 3 1 8 9 12 4 25 21 END
1 1 17 13 31 18 19 112 14 125 11 111 7 3 4 8 9 12 21 25 END
1 1 3 17 13 31 18 19 112 14 125 11 111 7 4 8 9 12 21 25 END
1 1 3 4 17 13 31 18 19 112 14 125 11 111 7 8 9 12 21 25 END
1 1 3 4 7 17 13 31 18 19 112 14 125 11 111 8 9 12 21 25 END
1 1 3 4 7 8 17 13 31 18 19 112 14 125 11 111 9 12 21 25 END
1 1 3 4 7 8 9 17 13 31 18 19 112 14 125 11 111 12 21 25 END
1 1 3 4 7 8 9 11 17 13 31 18 19 112 14 125 12 111 21 25 END
1 1 3 4 7 8 9 11 12 17 13 31 18 19 112 14 125 21 111 25 END
1 1 3 4 7 8 9 11 12 13 17 14 31 18 19 112 21 125 25 111 END
1 1 3 4 7 8 9 11 12 13 14 17 18 31 19 21 112 25 125 111 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 31 21 25 112 111 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 31 25 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
Method Quicksort:
3 13 1 4 12 9 14 8 11 1 7 17 111 125 112 19 18 25 31 21 END
1 1 3 4 12 9 14 8 11 13 7 END
1 1 END
1 1 3 4 12 9 14 8 11 13 7 END
1 1 3 4 11 9 7 8 12 13 14 END
1 1 3 4 8 9 7 11 END
1 1 3 4 7 8 9 END
1 1 3 4 7 8 9 11 12 13 14 END
1 1 3 4 7 8 9 11 12 13 14 17 25 21 31 19 18 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 19 21 18 25 31 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
Method heapSort:
Make heap:
17 13 31 18 19 112 14 125 11 111 7 3 1 8 9 12 4 25 1 21 END
17 13 31 18 19 112 14 125 25 111 7 3 1 8 9 12 4 11 1 21 END
17 13 31 18 19 112 14 125 25 111 7 3 1 8 9 12 4 11 1 21 END
17 13 31 18 19 112 14 125 25 111 7 3 1 8 9 12 4 11 1 21 END
17 13 31 18 19 112 14 125 25 111 7 3 1 8 9 12 4 11 1 21 END
17 13 31 18 111 112 14 125 25 21 7 3 1 8 9 12 4 11 1 19 END
17 13 31 125 111 112 14 18 25 21 7 3 1 8 9 12 4 11 1 19 END
17 13 112 125 111 31 14 18 25 21 7 3 1 8 9 12 4 11 1 19 END
17 125 112 25 111 31 14 18 13 21 7 3 1 8 9 12 4 11 1 19 END
125 111 112 25 21 31 14 18 13 19 7 3 1 8 9 12 4 11 1 17 END
125 111 112 25 21 31 14 18 13 19 7 3 1 8 9 12 4 11 1 17 END
Sort heap:
112 111 31 25 21 17 14 18 13 19 7 3 1 8 9 12 4 11 1 125 END
111 25 31 18 21 17 14 12 13 19 7 3 1 8 9 1 4 11 112 125 END
31 25 17 18 21 11 14 12 13 19 7 3 1 8 9 1 4 111 112 125 END
25 21 17 18 19 11 14 12 13 4 7 3 1 8 9 1 31 111 112 125 END
21 19 17 18 7 11 14 12 13 4 1 3 1 8 9 25 31 111 112 125 END
19 18 17 13 7 11 14 12 9 4 1 3 1 8 21 25 31 111 112 125 END
18 13 17 12 7 11 14 8 9 4 1 3 1 19 21 25 31 111 112 125 END
17 13 14 12 7 11 1 8 9 4 1 3 18 19 21 25 31 111 112 125 END
14 13 11 12 7 3 1 8 9 4 1 17 18 19 21 25 31 111 112 125 END
13 12 11 9 7 3 1 8 1 4 14 17 18 19 21 25 31 111 112 125 END
12 9 11 8 7 3 1 4 1 13 14 17 18 19 21 25 31 111 112 125 END
11 9 3 8 7 1 1 4 12 13 14 17 18 19 21 25 31 111 112 125 END
9 8 3 4 7 1 1 11 12 13 14 17 18 19 21 25 31 111 112 125 END
8 7 3 4 1 1 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
7 4 3 1 1 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
4 1 3 1 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
3 1 1 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END
1 1 3 4 7 8 9 11 12 13 14 17 18 19 21 25 31 111 112 125 END