Goto到另一个函数内部:实现

前文讨论了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

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值