lua-users home
lua-l archive

case statement for Lua

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I felt the need for a case statement in Lua, so I added one.
Unfortunately I had to change the virtual machine as well as the
compiler, because I couldn't figure out how to duplicate the element
on top of the stack using only the existing operators.
Still, Lua is so clean that I added or changed no more than 30 lines
of code.
I borrowed syntax from Modula-3 for the case statement (with one
slight change); here's an example:
 x = "bar"
 
 case x of
 | "foo" => y = 1
 | "bar" => y = 2
 else => y = 99 
 end
 
 print(x, y)
Some day when I have another hack attack, I'll improve the patch so
you can write multiple expressions to the left of the arrow.
This is a patch file for lua-2.5. To build it, unpack the lua-2.5
distribution, change to the toplevel directory (called 'lua' in the
distribution), and run
 patch < this_patch_file
 (cd src; make parser)
 make
Norman Ramsey
nr@cs.virginia.edu
*** ./src/luac/dump.c	1997年04月13日 05:24:05	1.1
--- ./src/luac/dump.c	1997年04月13日 05:24:24
***************
*** 42,47 ****
--- 42,48 ----
 	case PUSH0:
 	case PUSH1:
 	case PUSH2:
+ 	case DUP:
 	case PUSHLOCAL0:
 	case PUSHLOCAL1:
 	case PUSHLOCAL2:
*** ./src/luac/print.c	1997年04月13日 05:23:33	1.1
--- ./src/luac/print.c	1997年04月13日 05:23:48
***************
*** 3,9 ****
 ** print bytecodes
 */
 
! char* rcs_print="$Id: print.c,v 1.11 1996年11月18日 11:24:16 lhf Exp $";
 
 #include <stdio.h>
 #include <stdlib.h>
--- 3,9 ----
 ** print bytecodes
 */
 
! char* rcs_print="$Id: print.c,v 1.1 1997年04月13日 05:23:33 nr Exp nr $";
 
 #include <stdio.h>
 #include <stdlib.h>
***************
*** 32,37 ****
--- 32,38 ----
 	case PUSH0:
 	case PUSH1:
 	case PUSH2:
+ case DUP:
 	case PUSHINDEXED:
 	case STOREINDEXED0:
 	case ADJUST0:
*** ./src/luac/print.h	1997年04月13日 05:24:50	1.1
--- ./src/luac/print.h	1997年04月13日 05:25:09
***************
*** 9,14 ****
--- 9,15 ----
 "PUSH0",
 "PUSH1",
 "PUSH2",
+ "DUP",
 "PUSHBYTE",
 "PUSHWORD",
 "PUSHFLOAT",
*** ./src/lex.c	1997年04月13日 04:44:51	1.1
--- ./src/lex.c	1997年04月13日 04:46:48
***************
*** 48,53 ****
--- 48,54 ----
 int token;
 } reserved [] = {
 {"and", AND},
+ {"case", CASE},
 {"do", DO},
 {"else", ELSE},
 {"elseif", ELSEIF},
***************
*** 57,62 ****
--- 58,64 ----
 {"local", LOCAL},
 {"nil", NIL},
 {"not", NOT},
+ {"of", OF},
 {"or", OR},
 {"repeat", REPEAT},
 {"return", RETURN},
***************
*** 187,194 ****
 
 case '=':
 save_and_next();
! if (current != '=') return '=';
! else { save_and_next(); return EQ; }
 
 case '<':
 save_and_next();
--- 189,197 ----
 
 case '=':
 save_and_next();
! if (current == '>') { save_and_next(); return ARROW; }
! else if (current == '=') { save_and_next(); return EQ; }
! else return '=';
 
 case '<':
 save_and_next();
*** ./src/opcode.c	1997年04月13日 05:25:23	1.1
--- ./src/opcode.c	1997年04月13日 05:28:07
***************
*** 950,955 ****
--- 950,958 ----
 incr_top;
 break;
 
+ case DUP:
+ *top = *(top-1); incr_top; break;
+ 
 case PUSHBYTE: 
 tag(top) = LUA_T_NUMBER; nvalue(top) = *pc++; incr_top; break;
 
*** ./src/opcode.h	1997年04月13日 05:23:02	1.1
--- ./src/opcode.h	1997年04月13日 05:20:43
***************
*** 1,6 ****
 /*
 ** TeCGraf - PUC-Rio
! ** $Id: opcode.h,v 3.24 1996年11月01日 12:46:59 roberto Exp $
 */
 
 #ifndef opcode_h
--- 1,6 ----
 /*
 ** TeCGraf - PUC-Rio
! ** $Id: opcode.h,v 1.1 1997年04月13日 05:23:02 nr Exp nr $
 */
 
 #ifndef opcode_h
***************
*** 23,28 ****
--- 23,29 ----
 PUSH0,/*		-		0.0 */
 PUSH1,/*		-		1.0 */
 PUSH2,/*		-		2.0 */
+ DUP,/* x - x x */
 PUSHBYTE,/*	b	-		(float)b */
 PUSHWORD,/*	w	-		(float)w */
 PUSHFLOAT,/*	f	-		f */
*** ./src/undump.c	1997年04月13日 05:48:22	1.1
--- ./src/undump.c	1997年04月13日 05:29:13
***************
*** 3,9 ****
 ** load bytecodes from files
 */
 
! char* rcs_undump="$Id: undump.c,v 1.21 1996年11月18日 11:18:29 lhf Exp $";
 
 #include <stdio.h>
 #include <string.h>
--- 3,9 ----
 ** load bytecodes from files
 */
 
! char* rcs_undump="$Id: undump.c,v 1.1 1997年04月13日 05:48:22 nr Exp nr $";
 
 #include <stdio.h>
 #include <string.h>
***************
*** 36,41 ****
--- 36,42 ----
 	case PUSH0:
 	case PUSH1:
 	case PUSH2:
+ 	case DUP:
 	case PUSHLOCAL0:
 	case PUSHLOCAL1:
 	case PUSHLOCAL2:
*** src/lua.stx	1997年04月13日 04:44:51	1.1
--- src/lua.stx	1997年04月13日 05:30:26
***************
*** 426,436 ****
 
 %token WRONGTOKEN
 %token NIL
! %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL END
 %token RETURN
 %token LOCAL
 %token FUNCTION
 %token DOTS
 %token <vFloat> NUMBER
 %token <vWord> STRING
 %token <pTStr> NAME 
--- 426,437 ----
 
 %token WRONGTOKEN
 %token NIL
! %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL CASE OF END
 %token RETURN
 %token LOCAL
 %token FUNCTION
 %token DOTS
+ %token ARROW
 %token <vFloat> NUMBER
 %token <vWord> STRING
 %token <pTStr> NAME 
***************
*** 515,520 ****
--- 516,523 ----
 stat : IF expr1 THEN PrepJump block PrepJump elsepart END
 	{ codeIf(4,ドル 6ドル); }
 
+ | CASE expr1 OF case_body END
+ 
 | WHILE {$<vLong>$=pc;} expr1 DO PrepJump block PrepJump END
 {
 basepc[5ドル] = IFFJMP;
***************
*** 553,558 ****
--- 556,569 ----
 	{ codeIf(4,ドル 6ドル); }
 ;
 
+ case_body : '|' {code_byte(DUP);} expr1 {code_byte(EQOP);} PrepJump ARROW 
+ {code_byte(POP);} block PrepJump case_body
+ { codeIf(5,ドル 9ドル); }
+ /* should support multiple exprs */
+ | ELSE ARROW {code_byte(POP);} block 
+ | /* empty */ {code_byte(POP); /* should code for fallback here */ }
+ ;
+ 
 block : {$<vInt>$ = nlocalvar;} statlist ret 
 {
 	 if (nlocalvar != $<vInt>1)

AltStyle によって変換されたページ (->オリジナル) /