changeset 293:5bf2c3070d36

sort case value
author kono
date Sat, 05 Jun 2004 13:01:08 +0900
parents 6d4231b6f9fe
children ab715ae6b468
files mc-codegen.c mc-parse.c mc.h test/code-gen.c
diffstat 4 files changed, 91 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/mc-codegen.c	Sat Jun 05 00:08:09 2004 +0900
+++ b/mc-codegen.c	Sat Jun 05 13:01:08 2004 +0900
@@ -1772,12 +1772,17 @@
 
 #if CASE_CODE
 
+/*
+      cslist = list3(value,next,label)  label==0 means skip
+ */
+
 void
 cascade_compare(int cslist,int cslabel,int dlabel)
 {
     fwddef(cslabel);
     for(;cslist; cslist=cadr(cslist)) {
-	cmpdimm(car(cslist),csvalue1,caddr(cslist),0);
+	if (caddr(cslist))
+	    cmpdimm(car(cslist),csvalue1,caddr(cslist),0);
     }
     if (dlabel) jmp(dlabel);
 }
--- a/mc-parse.c	Sat Jun 05 00:08:09 2004 +0900
+++ b/mc-parse.c	Sat Jun 05 13:01:08 2004 +0900
@@ -1859,6 +1859,7 @@
 
     checkret();
     slist = cslist;
+    cslist = 0;
     sbreak=blabel;      /* save parents break label */
     blabel=fwdlabel();
     sdefault=dlabel;    /* save parents default label */
@@ -1870,6 +1871,7 @@
     slfree=lfree;
     svalue=csvalue1;      /* save parents switch value */
     gexpr(expr(0),1);
+    if (!scalar(type)) error(EXERR);
     csvalue1=csvalue() ;
     lfree=slfree;
     checksym(RPAR);
@@ -1907,15 +1909,22 @@
 }
 
 static void
+docase_eq()
+{
+    error(-1);  // duplicate case value
+}
+
+static void
 docase(void)
 {
 #if CASE_CODE
-    int l;
+    int l,clist=0,c;
     l = fwdlabel();
     while(sym==CASE) {
 	conv->case_begin_(0,0);
 	getsym(0);
-	cslist=list3(cexpr(expr(1)),cslist,l);
+	// temorary put into a list
+	clist=list3(cexpr(expr(1)),clist,l);
 	conv->case_(0,0);
 	checksym(COLON);
     }
@@ -1923,9 +1932,26 @@
     if (!cslabel) {
 	if (!control) {
 	    // immiediate after switch(i) (ususal case)
-	    cmpdimm(car(cslist),csvalue1,cslabel=fwdlabel(),1);
-	    cslist = cadr(cslist);
-	} else error(-1);  // checkret() sequence inconsistent
+	    // use it for jump to table lookup
+
+	    cmpdimm(car(clist),csvalue1,cslabel=fwdlabel(),1);
+
+	    // Insert anyway to check duplicate case value.
+	    // Mark it already used.
+
+	    caddr(clist)=0;
+
+	} else {
+	    // checkret() sequence inconsistent
+	    // This can't happen, because checkret() force teble lookup jump
+	    // before any executable instruction in switch such as siwth-for.
+	    error(-1);  
+	}
+    }
+    // Make ascend order list of case value
+    while(clist) {
+	clist = cadr(c=clist); cadr(c) = 0;  // insert destroy cadr of clist
+	cslist=insert_ascend(cslist,c,docase_eq);
     }
     fwddef(l);
     control=1;
@@ -4996,23 +5022,30 @@
     }
 }
 
-/* we can use cadr(e) = n; now. 
 int
-rplacad(int e, int n)
+insert_ascend(int p,int e,void eq())
 {
-    heap[e+1]=n;
-    return e;
+    int p1,p2;
+    if(!p) return e;
+    if (car(p)>car(e)) {
+	cadr(e) = p;
+	return e;
+    }
+    p1=p;
+    while(cadr(p)) {
+	p = cadr(p2=p);
+	if (car(p)==car(e)) eq();
+	if (car(p)>=car(e)) {
+	    cadr(e) = cadr(p2);
+	    cadr(p2) = e;
+	    return p1;
+	}
+    }
+    cadr(p) = e;
+    return p1;
 }
 
 int
-rplacadd(int e, int n)
-{
-    heap[e+2]=n;
-    return e;
-}
- */
-
-int
 append4(int p,int a1,int a2,int a3)
 {
     int p1;
--- a/mc.h	Sat Jun 05 00:08:09 2004 +0900
+++ b/mc.h	Sat Jun 05 13:01:08 2004 +0900
@@ -477,7 +477,7 @@
 extern int assign_expr0(int e1,int e2,int t,int type) ;
 extern int assign_expr(int e1,int e2,int t,int type) ;
 extern int append4(int p,int a1,int a2,int a3);
-
+extern int insert_ascend(int p,int e,void eq());
 
 
 #define car(e) (heap[(int)(e)])
--- a/test/code-gen.c	Sat Jun 05 00:08:09 2004 +0900
+++ b/test/code-gen.c	Sat Jun 05 13:01:08 2004 +0900
@@ -2635,6 +2635,40 @@
 	default: printf("code_switch d %d\n",i);
 	}
     }
+    for(i=0;i<10;i++) {
+	switch(i) {
+	case 1: printf("code_switch 1 %d\n",i); break;
+	case 2: 
+	    i = i* 100;
+	    switch(i) {
+	    case 100: printf("code_switch n 1 %d\n",i); break;
+	    case 200: 
+    for(i=-100;i<10;i++) {
+	switch(i) {
+	case 1234: printf("code_switch 1 nn %d\n",i); break;
+	case 2233: printf("code_switch 2 nn %d\n",i); break;
+	case 3333: printf("code_switch 3 nn %d\n",i);
+	case -4: printf("code_switch 4 nn %d\n",i); break;
+        case 733:
+	case -5: printf("code_switch 5 nn %d\n",i); break;
+	case -326: printf("code_switch 6 nn %d\n",i); 
+	}
+    }
+	    case 300: printf("code_switch n 3 %d\n",i);
+	    case 400: printf("code_switch n 4 %d\n",i); break;
+	    case 700:
+	    case 500: printf("code_switch n 5 %d\n",i); break;
+	    case 600: printf("code_switch n 6 %d\n",i); break;
+	    default: printf("code_switch n d %d\n",i);
+	    }
+	case 3: printf("code_switch 3 %d\n",i);
+	case 4: printf("code_switch 4 %d\n",i); break;
+        case 7:
+	case 5: printf("code_switch 5 %d\n",i); break;
+	case 6: printf("code_switch 6 %d\n",i); break;
+	default: printf("code_switch d %d\n",i);
+	}
+    }
 }