• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

BASIC compiler/interpreter for PIC32MX/MZ-80K


Commit MetaInfo

Revisãoe62bfb9afe5abbf484a001aff3884f25d648c448 (tree)
Hora2019-04-14 09:21:02
AutorKatsumi <kmorimatsu@sour...>
CommiterKatsumi

Mensagem de Log

Accept "_" for label/varnames. Correct protozoa button direction.

Mudança Sumário

Diff

--- a/mips/megalopa/compiler.h
+++ b/mips/megalopa/compiler.h
@@ -519,5 +519,9 @@ extern int g_int_vector[];
519519 #define div36_32(x) div32(x,0xe38e38e4,37)
520520 #define rem36_32(x) (x-36*div36_32(x))
521521
522+// Divide by 37 (valid for 31 bits)
523+#define div37_31(x) div32(x,0xdd67c8a7,37)
524+#define rem37_31(x) (x-37*div37_31(x))
525+
522526 // Check if within RAM
523527 #define withinRAM(x) ((&RAM[0])<=((char*)(x)) && ((char*)(x))<(&RAM[RAMSIZE]))
--- a/mips/megalopa/debug.c
+++ b/mips/megalopa/debug.c
@@ -228,14 +228,11 @@ static const char initext[]=
228228 "#PRINT\n";
229229
230230 static const char bastext[]=
231-"I=1:WHILE I<=10\n"
232-"I=I+1:WEND\n"
231+"CLS\n"
232+"LABEL TEST_:i=0/0\n"
233+"\n"
233234 "\n"
234-"I=1:DO\n"
235-"I=I+1:LOOP UNTIL I=11\n"
236235 "\n"
237-"FOR I=1 TO 10\n"
238-"NEXT\n"
239236 "\n"
240237 "\n"
241238 "\n";
--- a/mips/megalopa/envspecific.h
+++ b/mips/megalopa/envspecific.h
@@ -63,20 +63,19 @@ void err_peri_not_init(void);
6363
6464 #define ADDITIONAL_STR_FUNCTIONS
6565 #define ADDITIONAL_RESERVED_VAR_NAMES \
66- 0x00015045, /*OUT*/ \
67- 0x01975e81, /*OUT8H*/ \
68- 0x01975e85, /*OUT8L*/ \
69- 0x01975d7a, /*OUT16*/ \
70- 0x0001015b, /*IN*/ \
71- 0x0007dde1, /*IN8H*/ \
72- 0x0007dde5, /*IN8L*/ \
73- 0x0007dcda, /*IN16*/ \
74- 0x05f0a740, /*ANALOG*/ \
75- 0x00015596, /*PWM*/ \
76- 0x45f58f5d, /*SERIAL*/ \
77- 0x000163c6, /*SPI*/ \
78- 0x00012de4, /*I2C*/
79-
66+ 0x000154aa, /*OUT*/ \
67+ 0x01c5c253, /*OUT8H*/ \
68+ 0x01c5c257, /*OUT8L*/ \
69+ 0x01c5c145, /*OUT16*/ \
70+ 0x00010164, /*IN*/ \
71+ 0x000870fd, /*IN8H*/ \
72+ 0x00087101, /*IN8L*/ \
73+ 0x00086fef, /*IN16*/ \
74+ 0x06bd06f3, /*ANALOG*/ \
75+ 0x00015a46, /*PWM*/ \
76+ 0x502e9b15, /*SERIAL*/ \
77+ 0x0001694a, /*SPI*/ \
78+ 0x00013077, /*I2C*/ \
8079
8180 #define EXTRA_MASK 0x003F
8281 #define EXTRA_STEP 0x0001
--- a/mips/megalopa/error.c
+++ b/mips/megalopa/error.c
@@ -62,15 +62,16 @@ char* resolve_label(int s6){
6262 s6-=65536;
6363 str[6]=0x00;
6464 for(i=5;0<=i;i--){
65- if (s6<36) {
66- // First character must be A-Z, corresponding to 1-26 but not 10-35.
65+ if (s6<37) {
66+ // First character must be A-Z or _, corresponding to 1-27 but not 10-36.
6767 // See get_label() for the detail.
68- str[i]=s6-1+'A';
68+ if (s6==27) str[i]='_';
69+ else str[i]=s6-1+'A';
6970 break;
7071 } else {
71- // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
72- str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
73- s6=div36_32(s6);
72+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-36.
73+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_"[rem37_31(s6)];
74+ s6=div37_31(s6);
7475 }
7576 }
7677 return (char*)(str+i);
--- a/mips/megalopa/linker.c
+++ b/mips/megalopa/linker.c
@@ -44,17 +44,19 @@ char* get_label(void){
4444 g_label=0;
4545 return 0;
4646 }
47- } else if ('A'<=b1 && b1<='Z') {
47+ } else if ('A'<=b1 && b1<='Z' || b1=='_') {
4848 // May be label
49+ // When changing here, see also chech_var_name()
4950 do {
50- // First character must be A-Z
51- // From second, A-Z and 0-9 can be used.
52- i*=36;
51+ // First character must be A-Z or _
52+ // From second, A-Z, _, and 0-9 can be used.
53+ i*=37;
54+ if (b1=='_') b1='Z'+1;
5355 if ('0'<=b1 && b1<='9') {
5456 i+=b1-'0';
5557 } else if (g_srcpos==prevpos) {
56- // First character must be A-Z.
57- // Subtract 9, resulting 1-26 but not 10-35.
58+ // First character must be A-Z or _.
59+ // Subtract 9, resulting in 1-27 but not 10-36.
5860 // This subtraction is required to maintain
5961 // final number being <0x80000000.
6062 i+=b1-'A'+1;
@@ -63,7 +65,7 @@ char* get_label(void){
6365 }
6466 g_srcpos++;
6567 b1=g_source[g_srcpos];
66- } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
68+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z' || b1=='_');
6769 // Length of the label must be between 2 and 6.
6870 if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
6971 g_srcpos=prevpos;
--- a/mips/megalopa/reservednames.js
+++ b/mips/megalopa/reservednames.js
@@ -16,14 +16,15 @@ function name2int(name){
1616 var i=0;
1717 var b1=g_source.charCodeAt(0);
1818 do {
19- // First character must be A-Z
20- // From second, A-Z and 0-9 can be used.
21- i*=36;
19+ // First character must be A-Z or _
20+ // From second, A-Z, _, and 0-9 can be used.
21+ i*=37;
22+ if (b1=='_'.charCodeAt(0)) b1='Z'.charCodeAt(0)+1;
2223 if ('0'.charCodeAt(0)<=b1 && b1<='9'.charCodeAt(0)) {
2324 i+=b1-'0'.charCodeAt(0);
2425 } else if (g_srcpos==prevpos) {
25- // First character must be A-Z.
26- // Subtract 9, resulting 1-26 but not 10-35.
26+ // First character must be A-Z or _.
27+ // Subtract 9, resulting in 1-27 but not 10-36.
2728 // This subtraction is required to maintain
2829 // final number being <0x80000000.
2930 i+=b1-'A'.charCodeAt(0)+1;
@@ -32,10 +33,58 @@ function name2int(name){
3233 }
3334 g_srcpos++;
3435 b1=g_source.charCodeAt(g_srcpos);
35- } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
36+ } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || b1=='_'.charCodeAt(0) ||
37+ 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
3638 return i+65536;
3739 }
3840
41+function int2name(s6){
42+ var rem37_31=function(s6){
43+ return s6 % 37;
44+ };
45+ var div37_31=function(s6){
46+ return (s6-(s6 % 37))/37;
47+ };
48+ var str=new Array();
49+ var i,res;
50+ s6-=65536;
51+ str[6]=0;
52+ for(i=5;0<=i;i--){
53+ if (s6<37) {
54+ // First character must be A-Z or _, corresponding to 1-27 but not 10-36.
55+ // See get_label() for the detail.
56+ if (s6==27) str[i]='_'.charCodeAt(0);
57+ else str[i]=s6-1+'A'.charCodeAt(0);
58+ break;
59+ } else {
60+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-36.
61+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charCodeAt(rem37_31(s6));
62+ s6=div37_31(s6);
63+ }
64+ }
65+ //return (char*)(str+i);
66+ for(res='';str[i];i++) {
67+ res+=String.fromCharCode(str[i]);
68+ }
69+ return res;
70+}
71+
72+// Show max number by this system.
73+//WScript.Echo(name2int('______').toString(16));
74+
75+// Test functions for 10000 times with randomized var names
76+for(i=0;i<10000;i++){
77+ t="ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charAt(Math.random()*27);
78+ for(j=0;j<1+Math.random()*4;j++){
79+ t+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charAt(Math.random()*37);
80+ }
81+ j=name2int(t);
82+ if (int2name(j)!=t || j<0 || 0x7fffffff<j) {
83+ WScript.Echo('ERROR: '+t+' ('+j+'; 0x'+j.toString(16)+') '+i);
84+ WScript.Quit();
85+ }
86+}
87+
3988 var namearray=[
4089 'ABS',
4190 'ACOS',
@@ -168,14 +217,16 @@ var namearray=[
168217 'I2C',
169218 ];
170219 var result='';
220+var commented=0;
171221 for(key in namearray){
172222 var nameint='0000'+name2int(namearray[key]).toString(16);
173223 nameint=nameint.substr(nameint.length-8);
174224 if (namearray[key].substr(0,2)=='//') {
175225 // This is a comment
176226 result+=namearray[key]+"\r\n";
227+ commented=1;
177228 } else {
178- result+="\t0x"+nameint+", /*"+namearray[key]+"*/\r\n";
229+ result+="\t0x"+nameint+", /*"+namearray[key]+"*/"+(commented ? " \\\r\n" : "\r\n");
179230 }
180231 }
181232
--- a/mips/megalopa/statement.c
+++ b/mips/megalopa/statement.c
@@ -313,7 +313,7 @@ char* label_statement(){
313313 char* err;
314314 char b1;
315315 b1=g_source[g_srcpos];
316- if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
316+ if ('0'<=b1 && b1<='9') return ERR_SYNTAX; // Number is not allowed here.
317317 err=get_label();
318318 if (err) return err;
319319 // Check existing label with the same name here.
--- a/mips/megalopa/varname.c
+++ b/mips/megalopa/varname.c
@@ -18,120 +18,120 @@
1818 */
1919
2020 static const int reserved_var_names[]={
21- 0x000106b8, /*ABS*/
22- 0x0001f67c, /*ACOS*/
23- 0x0002414c, /*ARGS*/
24- 0x0001090c, /*ASC*/
25- 0x0002469f, /*ASIN*/
26- 0x00024a8f, /*ATAN*/
27- 0x002f7c1e, /*ATAN2*/
28- 0x0047c31c, /*BREAK*/
29- 0x00035869, /*CALL*/
30- 0x00575afe, /*CDATA*/
31- 0x00036c3d, /*CEIL*/
32- 0x000111af, /*CHR*/
33- 0x0cb1b682, /*CIRCLE*/
34- 0x005d1ea3, /*CLEAR*/
35- 0x00011240, /*CLS*/
36- 0x005f66cb, /*COLOR*/
37- 0x000112ac, /*COS*/
38- 0x0003a041, /*COSH*/
39- 0x00616415, /*CREAD*/
40- 0x0de593fb, /*CURSOR*/
41- 0x00040fbe, /*DATA*/
42- 0x00011644, /*DEC*/
43- 0x0fe19c42, /*DELETE*/
44- 0x000116de, /*DIM*/
45- 0x000100a8, /*DO*/
46- 0x0004fd8e, /*ELSE*/
47- 0x1434a177, /*ELSEIF*/
48- 0x00011c99, /*END*/
49- 0x0091c927, /*ENDIF*/
50- 0x00053854, /*EXEC*/
51- 0x00011e0d, /*EXP*/
52- 0x000579c8, /*FABS*/
53- 0x16e3d4be, /*FCLOSE*/
54- 0x00058fcf, /*FEOF*/
55- 0x00059895, /*FGET*/
56- 0x00a67500, /*FGETC*/
57- 0x00a7e061, /*FIELD*/
58- 0x0005a3a2, /*FILE*/
59- 0x177f0ca5, /*FINPUT*/
60- 0x0005b1df, /*FLEN*/
61- 0x00aa3445, /*FLOAT*/
62- 0x00aa363b, /*FLOOR*/
63- 0x0005b84d, /*FMOD*/
64- 0x00ac5c9f, /*FOPEN*/
65- 0x000121db, /*FOR*/
66- 0x18352839, /*FPRINT*/
67- 0x0005c865, /*FPUT*/
68- 0x00ad2e40, /*FPUTC*/
69- 0x00aefdec, /*FSEEK*/
70- 0x00063b90, /*GCLS*/
71- 0x1a808bcb, /*GCOLOR*/
72- 0x1ab733b3, /*GETDIR*/
73- 0x00c60f03, /*GOSUB*/
74- 0x0006796c, /*GOTO*/
75- 0x1bcfcc39, /*GPRINT*/
76- 0x00012a99, /*HEX*/
77- 0x0007ad12, /*IDLE*/
78- 0x00010153, /*IF*/
79- 0x00f8701a, /*INKEY*/
80- 0x00f88ba5, /*INPUT*/
81- 0x000130e9, /*INT*/
82- 0x00092084, /*KEYS*/
83- 0x013be43d, /*LABEL*/
84- 0x00013ecf, /*LEN*/
85- 0x00013ed5, /*LET*/
86- 0x0009e96a, /*LINE*/
87- 0x00014030, /*LOG*/
88- 0x0145f324, /*LOG10*/
89- 0x000a07f9, /*LOOP*/
90- 0x000abca3, /*MODF*/
91- 0x016418d4, /*MUSIC*/
92- 0x000b4321, /*NEXT*/
93- 0x000148f8, /*NEW*/
94- 0x00014a5d, /*NOT*/
95- 0x38a658d7, /*OPTION*/
96- 0x000152c0, /*PCG*/
97- 0x000cacec, /*PEEK*/
98- 0x3b1c6aea, /*PEEK16*/
99- 0x3b1c6b2e, /*PEEK32*/
100- 0x00010252, /*PI*/
101- 0x01ac8479, /*POINT*/
102- 0x000ce05e, /*POKE*/
103- 0x3c20dc0a, /*POKE16*/
104- 0x3c20dc4e, /*POKE32*/
105- 0x00015480, /*POW*/
106- 0x01aea739, /*PRINT*/
107- 0x000cf3d5, /*PSET*/
108- 0x3cb45fa4, /*PUBLIC*/
109- 0x3cc0fe21, /*PUTBMP*/
110- 0x000e18d5, /*READ*/
111- 0x00015d2e, /*REM*/
112- 0x425c9703, /*RETURN*/
113- 0x00015e69, /*RND*/
114- 0x45c26d49, /*SCROLL*/
115- 0x45f6e3b3, /*SETDIR*/
116- 0x00016287, /*SGN*/
117- 0x000162cf, /*SIN*/
118- 0x000ee52d, /*SINH*/
119- 0x01f9a429, /*SOUND*/
120- 0x000f0e49, /*SQRT*/
121- 0x47f711de, /*SYSTEM*/
122- 0x000166bf, /*TAN*/
123- 0x000f72ed, /*TANH*/
124- 0x020ed5f3, /*TIMER*/
125- 0x02182fee, /*TVRAM*/
126- 0x022c2a2d, /*UNTIL*/
127- 0x4e8887d0, /*USEPCG*/
128- 0x4e88a5f3, /*USEVAR*/
129- 0x000170dd, /*VAL*/
130- 0x000170e3, /*VAR*/
131- 0x00119505, /*WAIT*/
132- 0x0011a9e9, /*WEND*/
133- 0x025aef62, /*WHILE*/
134- 0x025b8d75, /*WIDTH*/
21+ 0x0001070c, /*ABS*/
22+ 0x0002099d, /*ACOS*/
23+ 0x000258ac, /*ARGS*/
24+ 0x00010971, /*ASC*/
25+ 0x00025e4a, /*ASIN*/
26+ 0x0002627b, /*ATAN*/
27+ 0x00343bc9, /*ATAN2*/
28+ 0x004f5c95, /*BREAK*/
29+ 0x00038a2f, /*CALL*/
30+ 0x006110c1, /*CDATA*/
31+ 0x00039f24, /*CEIL*/
32+ 0x0001129b, /*CHR*/
33+ 0x0e7f3303, /*CIRCLE*/
34+ 0x0067525f, /*CLEAR*/
35+ 0x00011330, /*CLS*/
36+ 0x0069cb6b, /*COLOR*/
37+ 0x0001139f, /*COS*/
38+ 0x0003d60c, /*COSH*/
39+ 0x006bf57f, /*CREAD*/
40+ 0x0fd6b45b, /*CURSOR*/
41+ 0x00045129, /*DATA*/
42+ 0x00011776, /*DEC*/
43+ 0x122a52c0, /*DELETE*/
44+ 0x00011814, /*DIM*/
45+ 0x000100ac, /*DO*/
46+ 0x000551b8, /*ELSE*/
47+ 0x171a03a1, /*ELSEIF*/
48+ 0x00011e1d, /*END*/
49+ 0x00a20bbe, /*ENDIF*/
50+ 0x00058fdc, /*EXEC*/
51+ 0x00011f9b, /*EXP*/
52+ 0x0005da5b, /*FABS*/
53+ 0x1a358bdd, /*FCLOSE*/
54+ 0x0005f193, /*FEOF*/
55+ 0x0005fae1, /*FGET*/
56+ 0x00b94291, /*FGETC*/
57+ 0x00bacd24, /*FIELD*/
58+ 0x00060687, /*FILE*/
59+ 0x1ae2b2ef, /*FINPUT*/
60+ 0x00061598, /*FLEN*/
61+ 0x00bd52ae, /*FLOAT*/
62+ 0x00bd54b2, /*FLOOR*/
63+ 0x00061c59, /*FMOD*/
64+ 0x00bfaa2c, /*FOPEN*/
65+ 0x000123a9, /*FOR*/
66+ 0x1badd288, /*FPRINT*/
67+ 0x00062d52, /*FPUT*/
68+ 0x00c08ce6, /*FPUTC*/
69+ 0x00c286ca, /*FSEEK*/
70+ 0x0006ac5c, /*GCLS*/
71+ 0x1e59e7b7, /*GCOLOR*/
72+ 0x1e96cb44, /*GETDIR*/
73+ 0x00dc556c, /*GOSUB*/
74+ 0x0006edac, /*GOTO*/
75+ 0x1fcfed5d, /*GPRINT*/
76+ 0x00012cef, /*HEX*/
77+ 0x00083d61, /*IDLE*/
78+ 0x0001015c, /*IF*/
79+ 0x01149470, /*INKEY*/
80+ 0x0114b178, /*INPUT*/
81+ 0x00013391, /*INT*/
82+ 0x0009d063, /*KEYS*/
83+ 0x016022dc, /*LABEL*/
84+ 0x00014249, /*LEN*/
85+ 0x0001424f, /*LET*/
86+ 0x000aa9ff, /*LINE*/
87+ 0x000143b4, /*LOG*/
88+ 0x016b0db9, /*LOG10*/
89+ 0x000aca45, /*LOOP*/
90+ 0x000b8e81, /*MODF*/
91+ 0x018c8c85, /*MUSIC*/
92+ 0x000c21d6, /*NEXT*/
93+ 0x00014d04, /*NEW*/
94+ 0x00014e73, /*NOT*/
95+ 0x40e24fde, /*OPTION*/
96+ 0x0001575c, /*PCG*/
97+ 0x000daac8, /*PEEK*/
98+ 0x43be47b3, /*PEEK16*/
99+ 0x43be47f9, /*PEEK32*/
100+ 0x00010262, /*PI*/
101+ 0x01dd7f7a, /*POINT*/
102+ 0x000de11a, /*POKE*/
103+ 0x44e0c435, /*POKE16*/
104+ 0x44e0c47b, /*POKE32*/
105+ 0x00015928, /*POW*/
106+ 0x01dfd111, /*PRINT*/
107+ 0x000df5af, /*PSET*/
108+ 0x45858d00, /*PUBLIC*/
109+ 0x459341b1, /*PUTBMP*/
110+ 0x000f35e7, /*READ*/
111+ 0x0001625e, /*REM*/
112+ 0x4c0e4e9d, /*RETURN*/
113+ 0x000163a2, /*RND*/
114+ 0x4ff58ae0, /*SCROLL*/
115+ 0x50300d40, /*SETDIR*/
116+ 0x00016802, /*SGN*/
117+ 0x0001684c, /*SIN*/
118+ 0x0010130d, /*SINH*/
119+ 0x02338a69, /*SOUND*/
120+ 0x00103e75, /*SQRT*/
121+ 0x526b8f2e, /*SYSTEM*/
122+ 0x00016c7d, /*TAN*/
123+ 0x0010ae22, /*TANH*/
124+ 0x024b5425, /*TIMER*/
125+ 0x02557a82, /*TVRAM*/
126+ 0x026bf064, /*UNTIL*/
127+ 0x59f94768, /*USEPCG*/
128+ 0x59f9673f, /*USEVAR*/
129+ 0x0001772d, /*VAL*/
130+ 0x00017733, /*VAR*/
131+ 0x0012ff0c, /*WAIT*/
132+ 0x00131519, /*WEND*/
133+ 0x02a044ad, /*WHILE*/
134+ 0x02a0f0f8, /*WIDTH*/
135135 // Additional names follow
136136 ADDITIONAL_RESERVED_VAR_NAMES
137137 };
@@ -150,16 +150,18 @@ int check_var_name(){
150150 int prevpos=g_srcpos;
151151 next_position();
152152 b1=g_source[g_srcpos];
153- if (b1<'A' || 'Z'<b1) return -1;
153+ // When changing here, see also get_label()
154+ if ((b1<'A' || 'Z'<b1) && b1!='_') return -1;
154155 do {
155- // First character must be A-Z
156- // From second, A-Z and 0-9 can be used.
157- i*=36;
156+ // First character must be A-Z or _
157+ // From second, A-Z, _, and 0-9 can be used.
158+ i*=37;
159+ if (b1=='_') b1='Z'+1;
158160 if ('0'<=b1 && b1<='9') {
159161 i+=b1-'0';
160162 } else if (g_srcpos==prevpos) {
161- // First character must be A-Z.
162- // Subtract 9, resulting 1-26 but not 10-35.
163+ // First character must be A-Z or _.
164+ // Subtract 9, resulting 1-27 but not 10-36.
163165 // This subtraction is required to maintain
164166 // final number being <0x80000000.
165167 i+=b1-'A'+1;
@@ -168,7 +170,7 @@ int check_var_name(){
168170 }
169171 g_srcpos++;
170172 b1=g_source[g_srcpos];
171- } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
173+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z' || b1=='_');
172174 // Length of the label must be between 2 and 6.
173175 if (g_srcpos-prevpos<2) {
174176 // One letter var name, A-Z
--- /dev/null
+++ b/mips/protozoa/class.txt
@@ -0,0 +1,170 @@
1+<クラスとオブジェクトの利用方法>
2+
3+ここでは、オブジェクト指向プログラミングについて述べます。MachiKaniaでは、クラス
4+ベースのオブジェクト指向プログラミングが可能です。次のような特徴があります。
5+
6+ 1)オブジェクトは、フィールド(public もしくは private)とメソッド(public のみ)
7+ を持つ。
8+ 2)クラスの記述は別ファイルに於いて行ない、1ファイルに1クラスの記述とする。
9+ 3)複数のクラスを利用出来る。また、クラス中で別のクラスを利用出来る。
10+ 4)クラスの継承は、未実装。
11+ 5)フィールド名とメソッド名には、2文字以上6文字以内の英数字が指定出来る。
12+
13+別ファイルとしてクラスを記述し、このファイルをクラス指定する事で、複数のファイル
14+からなるプログラムを作成する事が可能です。クラス間の接続はフィールドとメソッドを
15+介してのみ行なわれます。したがって、同じ名前の変数やラベルが複数のファイルに於い
16+て存在していたとしても、それぞれファイルごとに制御が行なわれますので、名前の衝突
17+が起きる事はありません。
18+
19+<クラスの記述の仕方>
20+
21+クラスを作成するには、"クラス名.BAS"の名でテキストファイルを準備します。ただし、
22+クラス名は2文字以上6文字以内の英数字です。クラスファイルでは、FIELD, STATIC,
23+METHOD命令が必須です(どれか1種類だけでも使えます)。
24+
25+FIELD [PUBLIC] x[,y[,z[, ... ]]]
26+ クラスファイル中で、パブリックフィールドを宣言する。"PUBLIC"は省略可。
27+ x,y,z等はフィールド名を6文字以内の英数字で指定。ただし、フィールドを文字列型
28+ で使う場合は、「$」をフィールド名の後ろに付ける。
29+FIELD PRIVATE x[,y[,z[, ... ]]]
30+ クラスファイル中で、プライベートフィールドを宣言する。x,y,z等はフィールド
31+ 名を6文字以内の英数字で指定。ただし、フィールドを文字列型で使う場合は「$」を
32+ フィールド名の後ろに付け、配列として使う場合は「()」を付ける。
33+STATIC [PUBLIC] x[,y[,z[, ... ]]]
34+ クラスファイル中で、パブリックスなタティック変数を宣言する。"PUBLIC"は省略可。
35+STATIC PRIVATE x[,y[,z[, ... ]]]
36+ クラスファイル中で、プライベートなスタティック変数を宣言する。USEVARと同じ。
37+METHOD x
38+ クラスファイル中で、メソッドを宣言する。xは、メソッド名を6文字以内の英
39+ 数字で指定。
40+
41+クラスファイル中でフィールド値(パブリック・プライベートの両方)にアクセスする場
42+合は、FIELD指定した長い名前の変数に直接アクセス(読み込み及び書き込み)して下さい。
43+「THIS」などの表記は必要ありません。
44+
45+オブジェクトのフィールドではないスタティックな変数を扱いたい時は、STATICもしくは
46+USEVAR命令を使って下さい。ここで使用した長い名前の変数は、他のファイルでの同一名
47+の変数の値に影響しません。ただし、変数A-Zの読み出し・変更は、他のファイルで使用
48+する値に影響します。
49+
50+METHOD命令で宣言されたメソッドは、すべてパブリックです。プライベートなサブルー
51+チン呼び出しには、LABEL命令とGOSUB命令/関数を用いて下さい。メソッド呼び出しの際
52+の引数は、ARGS()関数で取り出す事が可能です。メソッド中で自身のオブジェクトへの
53+ポインターが必要な場合は、ARGS(-2)で取り出す事が出来ます。
54+
55+コンストラクターを指定する場合は、「METHOD INIT」として下さい。このようにINIT
56+メソッドが指定された場合、オブジェクト作成時に、このメソッドが呼ばれます。INIT
57+メソッドに引数を与える事も可能です(引数は必須ではありません)。
58+
59+クラス中でオブジェクトへのポインターが必要な場合は、ARGS(-2)で取り出す事が出来
60+ます。
61+
62+記述例(CLASS1.BASの名前で保存):
63+ FIELD PUBLIC TEST1,TEST2
64+ FIELD PRIVATE TEST3
65+ STATIC PUBLIC TEST7
66+ METHOD INIT
67+  IF ARGS(0)=2 THEN
68+   TEST1=ARGS(1)
69+   TEST2=ARGS(2)
70+  ENDIF
71+ RETURN
72+ METHOD TEST4
73+  TEST1=ARGS(1)
74+  TEST2=ARGS(2)
75+ RETURN
76+ METHOD TEST5
77+  TEST3=TEST1+TEST2+TEST7
78+ RETURN
79+ METHOD TEST6
80+ RETURN TEST3
81+ METHOD TEST8
82+ RETURN TEST7
83+
84+<オブジェクトの作成方法>
85+
86+オブジェクトを作成するためには、まずUSECLASS命令で使用するクラスを指定し、次に
87+NEW関数を用います。
88+
89+USECLASS x[,y[,z[, ... ]]]
90+ クラスの利用を宣言する。x,y,z等は、クラス名を6文字以内の英数字で指定。
91+NEW(x[,y[,z[, ... ]]])
92+ クラスオブジェクトを作成し、オブジェクトへのポインターを返す。xはクラス名
93+ を指定。y,z等はコンストラクターがある際に利用される引数。
94+
95+記述例1:
96+ USECLASS CLASS1
97+ A=NEW(CLASS1)
98+
99+記述例2(コンストラクターに引数を指定する場合):
100+ USECLASS CLASS1
101+ A=NEW(CLASS1,123,456)
102+
103+<オブジェクトの破棄方法>
104+
105+作成したオブジェクトは、DELETE命令を用いて破棄する事も出来ます。ただし、デストラ
106+クターは実装していませんので、必要ならば、それ用のメソッドを作成して破棄する直前に
107+呼び出して下さい。
108+
109+オブジェクトのフィールドに文字列もしくは配列を用いている場合、オブジェクトを
110+DELETEするだけではこれらの領域は破棄されません。その場合、まずメソッド内でこれら
111+のフィールドを破棄(DELETE命令が使えます)してから、オブジェクトを破棄するようにし
112+て下さい。
113+
114+記述例:
115+ USECLASS CLASS1
116+ A=NEW(CLASS1)
117+ DELETE A
118+
119+<フィールドへのアクセス方法>
120+
121+パブリックフィールドへアクセスする場合は、オブジェクトを含む変数に続けて「.」と
122+フィールド名を記述して下さい。フィールドが文字列の場合は「$」を、実数の場合は
123+「#」を、それぞれ後ろに付けて下さい。
124+
125+記述例:
126+ USECLASS CLASS1
127+ A=NEW(CLASS1)
128+ A.TEST1=123
129+ PRINT A.TEST2
130+
131+<メソッドへのアクセス方法>
132+
133+パブリックメソッドへアクセスする場合は、オブジェクトを含む変数に続けて「.」と
134+メソッド名、続けて「( )」を記述して下さい。メソッドが戻り値として文字列を返す場
135+合、メソッド名の後ろに「$」を付けて下さい(実数の場合は「#」)。メソッドは関数
136+と同じ扱いですが、戻り値を利用しない場合は、CALL命令により呼び出す事も出来ます。
137+
138+CALL x
139+ xで指定されたオブジェクトのメソッドを呼び出す。
140+
141+記述例(579が表示される):
142+ USECLASS CLASS1
143+ A=NEW(CLASS1)
144+ CALL A.TEST4(123,456)
145+ CALL A.TEST5()
146+ PRINT A.TEST6()
147+
148+<スタティック変数・スタティックメソッドの利用>
149+
150+クラス中で"STATIC PUBLIC"で指定された変数は、外部から値を参照したり、値を変更
151+したりすることが出来ます。この場合、クラス名に続けて「::」と変数名を記述して下
152+さい。
153+
154+また、それぞれのメソッドは、スタティックメソッドとして利用する事も出来ます。こ
155+の場合、クラス名に続けて「::」とメソッド名、続けて「( )」を記述して下さい。
156+
157+記述例(123が表示される):
158+ USECLASS CLASS1
159+ CLASS1::TEST6=123
160+ PRINT CLASS1::TEST7()
161+
162+<ライブラリーについて>
163+
164+クラスファイルは、カレントディレクトリーに「クラス名.BAS」ファイルが有れば、読み
165+出されます。もしカレントディレクトリーに無ければ、「\LIB\クラス名\クラス名.BAS」
166+を探し、有ればそれが読み出されます。従って、「\LIB」ディレクトリーにクラス群を
167+配置しておけば、いつでも使用可能なライブラリーとして使えます。
168+
169+<バージョン履歴>
170+・KM-1207/KM1302 2019年3月公開。
--- a/mips/protozoa/compiler.h
+++ b/mips/protozoa/compiler.h
@@ -519,5 +519,9 @@ extern int g_int_vector[];
519519 #define div36_32(x) div32(x,0xe38e38e4,37)
520520 #define rem36_32(x) (x-36*div36_32(x))
521521
522+// Divide by 37 (valid for 31 bits)
523+#define div37_31(x) div32(x,0xdd67c8a7,37)
524+#define rem37_31(x) (x-37*div37_31(x))
525+
522526 // Check if within RAM
523527 #define withinRAM(x) ((&RAM[0])<=((char*)(x)) && ((char*)(x))<(&RAM[RAMSIZE]))
--- a/mips/protozoa/debug.c
+++ b/mips/protozoa/debug.c
@@ -228,14 +228,11 @@ static const char initext[]=
228228 "#PRINT\n";
229229
230230 static const char bastext[]=
231-"I=1:WHILE I<=10\n"
232-"I=I+1:WEND\n"
231+"CLS\n"
232+"LABEL TEST_:i=0/0\n"
233+"\n"
233234 "\n"
234-"I=1:DO\n"
235-"I=I+1:LOOP UNTIL I=11\n"
236235 "\n"
237-"FOR I=1 TO 10\n"
238-"NEXT\n"
239236 "\n"
240237 "\n"
241238 "\n";
--- a/mips/protozoa/error.c
+++ b/mips/protozoa/error.c
@@ -62,15 +62,16 @@ char* resolve_label(int s6){
6262 s6-=65536;
6363 str[6]=0x00;
6464 for(i=5;0<=i;i--){
65- if (s6<36) {
66- // First character must be A-Z, corresponding to 1-26 but not 10-35.
65+ if (s6<37) {
66+ // First character must be A-Z or _, corresponding to 1-27 but not 10-36.
6767 // See get_label() for the detail.
68- str[i]=s6-1+'A';
68+ if (s6==27) str[i]='_';
69+ else str[i]=s6-1+'A';
6970 break;
7071 } else {
71- // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
72- str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
73- s6=div36_32(s6);
72+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-36.
73+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_"[rem37_31(s6)];
74+ s6=div37_31(s6);
7475 }
7576 }
7677 return (char*)(str+i);
--- a/mips/protozoa/interface/videoout.h
+++ b/mips/protozoa/interface/videoout.h
@@ -26,10 +26,10 @@
2626 #define KEYRIGHT 0x0010
2727 #define KEYUP 0x0020
2828 #else
29- #define KEYLEFT 0x0004
30- #define KEYUP 0x0008
31- #define KEYDOWN 0x0010
32- #define KEYRIGHT 0x0020
29+ #define KEYRIGHT 0x0004
30+ #define KEYDOWN 0x0008
31+ #define KEYUP 0x0010
32+ #define KEYLEFT 0x0020
3333 #endif
3434 #define KEYSTART 0x0080
3535 #define KEYFIRE 0x0100
--- a/mips/protozoa/linker.c
+++ b/mips/protozoa/linker.c
@@ -44,17 +44,19 @@ char* get_label(void){
4444 g_label=0;
4545 return 0;
4646 }
47- } else if ('A'<=b1 && b1<='Z') {
47+ } else if ('A'<=b1 && b1<='Z' || b1=='_') {
4848 // May be label
49+ // When changing here, see also chech_var_name()
4950 do {
50- // First character must be A-Z
51- // From second, A-Z and 0-9 can be used.
52- i*=36;
51+ // First character must be A-Z or _
52+ // From second, A-Z, _, and 0-9 can be used.
53+ i*=37;
54+ if (b1=='_') b1='Z'+1;
5355 if ('0'<=b1 && b1<='9') {
5456 i+=b1-'0';
5557 } else if (g_srcpos==prevpos) {
56- // First character must be A-Z.
57- // Subtract 9, resulting 1-26 but not 10-35.
58+ // First character must be A-Z or _.
59+ // Subtract 9, resulting in 1-27 but not 10-36.
5860 // This subtraction is required to maintain
5961 // final number being <0x80000000.
6062 i+=b1-'A'+1;
@@ -63,7 +65,7 @@ char* get_label(void){
6365 }
6466 g_srcpos++;
6567 b1=g_source[g_srcpos];
66- } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
68+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z' || b1=='_');
6769 // Length of the label must be between 2 and 6.
6870 if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
6971 g_srcpos=prevpos;
--- a/mips/protozoa/reservednames.js
+++ b/mips/protozoa/reservednames.js
@@ -16,14 +16,15 @@ function name2int(name){
1616 var i=0;
1717 var b1=g_source.charCodeAt(0);
1818 do {
19- // First character must be A-Z
20- // From second, A-Z and 0-9 can be used.
21- i*=36;
19+ // First character must be A-Z or _
20+ // From second, A-Z, _, and 0-9 can be used.
21+ i*=37;
22+ if (b1=='_'.charCodeAt(0)) b1='Z'.charCodeAt(0)+1;
2223 if ('0'.charCodeAt(0)<=b1 && b1<='9'.charCodeAt(0)) {
2324 i+=b1-'0'.charCodeAt(0);
2425 } else if (g_srcpos==prevpos) {
25- // First character must be A-Z.
26- // Subtract 9, resulting 1-26 but not 10-35.
26+ // First character must be A-Z or _.
27+ // Subtract 9, resulting in 1-27 but not 10-36.
2728 // This subtraction is required to maintain
2829 // final number being <0x80000000.
2930 i+=b1-'A'.charCodeAt(0)+1;
@@ -32,10 +33,58 @@ function name2int(name){
3233 }
3334 g_srcpos++;
3435 b1=g_source.charCodeAt(g_srcpos);
35- } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
36+ } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || b1=='_'.charCodeAt(0) ||
37+ 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
3638 return i+65536;
3739 }
3840
41+function int2name(s6){
42+ var rem37_31=function(s6){
43+ return s6 % 37;
44+ };
45+ var div37_31=function(s6){
46+ return (s6-(s6 % 37))/37;
47+ };
48+ var str=new Array();
49+ var i,res;
50+ s6-=65536;
51+ str[6]=0;
52+ for(i=5;0<=i;i--){
53+ if (s6<37) {
54+ // First character must be A-Z or _, corresponding to 1-27 but not 10-36.
55+ // See get_label() for the detail.
56+ if (s6==27) str[i]='_'.charCodeAt(0);
57+ else str[i]=s6-1+'A'.charCodeAt(0);
58+ break;
59+ } else {
60+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-36.
61+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charCodeAt(rem37_31(s6));
62+ s6=div37_31(s6);
63+ }
64+ }
65+ //return (char*)(str+i);
66+ for(res='';str[i];i++) {
67+ res+=String.fromCharCode(str[i]);
68+ }
69+ return res;
70+}
71+
72+// Show max number by this system.
73+//WScript.Echo(name2int('______').toString(16));
74+
75+// Test functions for 10000 times with randomized var names
76+for(i=0;i<10000;i++){
77+ t="ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charAt(Math.random()*27);
78+ for(j=0;j<1+Math.random()*4;j++){
79+ t+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charAt(Math.random()*37);
80+ }
81+ j=name2int(t);
82+ if (int2name(j)!=t || j<0 || 0x7fffffff<j) {
83+ WScript.Echo('ERROR: '+t+' ('+j+'; 0x'+j.toString(16)+') '+i);
84+ WScript.Quit();
85+ }
86+}
87+
3988 var namearray=[
4089 'ABS',
4190 'ACOS',
@@ -168,14 +217,16 @@ var namearray=[
168217 'I2C',
169218 ];
170219 var result='';
220+var commented=0;
171221 for(key in namearray){
172222 var nameint='0000'+name2int(namearray[key]).toString(16);
173223 nameint=nameint.substr(nameint.length-8);
174224 if (namearray[key].substr(0,2)=='//') {
175225 // This is a comment
176226 result+=namearray[key]+"\r\n";
227+ commented=1;
177228 } else {
178- result+="\t0x"+nameint+", /*"+namearray[key]+"*/\r\n";
229+ result+="\t0x"+nameint+", /*"+namearray[key]+"*/"+(commented ? " \\\r\n" : "\r\n");
179230 }
180231 }
181232
--- a/mips/protozoa/statement.c
+++ b/mips/protozoa/statement.c
@@ -313,7 +313,7 @@ char* label_statement(){
313313 char* err;
314314 char b1;
315315 b1=g_source[g_srcpos];
316- if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
316+ if ('0'<=b1 && b1<='9') return ERR_SYNTAX; // Number is not allowed here.
317317 err=get_label();
318318 if (err) return err;
319319 // Check existing label with the same name here.
--- a/mips/protozoa/varname.c
+++ b/mips/protozoa/varname.c
@@ -18,120 +18,120 @@
1818 */
1919
2020 static const int reserved_var_names[]={
21- 0x000106b8, /*ABS*/
22- 0x0001f67c, /*ACOS*/
23- 0x0002414c, /*ARGS*/
24- 0x0001090c, /*ASC*/
25- 0x0002469f, /*ASIN*/
26- 0x00024a8f, /*ATAN*/
27- 0x002f7c1e, /*ATAN2*/
28- 0x0047c31c, /*BREAK*/
29- 0x00035869, /*CALL*/
30- 0x00575afe, /*CDATA*/
31- 0x00036c3d, /*CEIL*/
32- 0x000111af, /*CHR*/
33- 0x0cb1b682, /*CIRCLE*/
34- 0x005d1ea3, /*CLEAR*/
35- 0x00011240, /*CLS*/
36- 0x005f66cb, /*COLOR*/
37- 0x000112ac, /*COS*/
38- 0x0003a041, /*COSH*/
39- 0x00616415, /*CREAD*/
40- 0x0de593fb, /*CURSOR*/
41- 0x00040fbe, /*DATA*/
42- 0x00011644, /*DEC*/
43- 0x0fe19c42, /*DELETE*/
44- 0x000116de, /*DIM*/
45- 0x000100a8, /*DO*/
46- 0x0004fd8e, /*ELSE*/
47- 0x1434a177, /*ELSEIF*/
48- 0x00011c99, /*END*/
49- 0x0091c927, /*ENDIF*/
50- 0x00053854, /*EXEC*/
51- 0x00011e0d, /*EXP*/
52- 0x000579c8, /*FABS*/
53- 0x16e3d4be, /*FCLOSE*/
54- 0x00058fcf, /*FEOF*/
55- 0x00059895, /*FGET*/
56- 0x00a67500, /*FGETC*/
57- 0x00a7e061, /*FIELD*/
58- 0x0005a3a2, /*FILE*/
59- 0x177f0ca5, /*FINPUT*/
60- 0x0005b1df, /*FLEN*/
61- 0x00aa3445, /*FLOAT*/
62- 0x00aa363b, /*FLOOR*/
63- 0x0005b84d, /*FMOD*/
64- 0x00ac5c9f, /*FOPEN*/
65- 0x000121db, /*FOR*/
66- 0x18352839, /*FPRINT*/
67- 0x0005c865, /*FPUT*/
68- 0x00ad2e40, /*FPUTC*/
69- 0x00aefdec, /*FSEEK*/
70- 0x00063b90, /*GCLS*/
71- 0x1a808bcb, /*GCOLOR*/
72- 0x1ab733b3, /*GETDIR*/
73- 0x00c60f03, /*GOSUB*/
74- 0x0006796c, /*GOTO*/
75- 0x1bcfcc39, /*GPRINT*/
76- 0x00012a99, /*HEX*/
77- 0x0007ad12, /*IDLE*/
78- 0x00010153, /*IF*/
79- 0x00f8701a, /*INKEY*/
80- 0x00f88ba5, /*INPUT*/
81- 0x000130e9, /*INT*/
82- 0x00092084, /*KEYS*/
83- 0x013be43d, /*LABEL*/
84- 0x00013ecf, /*LEN*/
85- 0x00013ed5, /*LET*/
86- 0x0009e96a, /*LINE*/
87- 0x00014030, /*LOG*/
88- 0x0145f324, /*LOG10*/
89- 0x000a07f9, /*LOOP*/
90- 0x000abca3, /*MODF*/
91- 0x016418d4, /*MUSIC*/
92- 0x000b4321, /*NEXT*/
93- 0x000148f8, /*NEW*/
94- 0x00014a5d, /*NOT*/
95- 0x38a658d7, /*OPTION*/
96- 0x000152c0, /*PCG*/
97- 0x000cacec, /*PEEK*/
98- 0x3b1c6aea, /*PEEK16*/
99- 0x3b1c6b2e, /*PEEK32*/
100- 0x00010252, /*PI*/
101- 0x01ac8479, /*POINT*/
102- 0x000ce05e, /*POKE*/
103- 0x3c20dc0a, /*POKE16*/
104- 0x3c20dc4e, /*POKE32*/
105- 0x00015480, /*POW*/
106- 0x01aea739, /*PRINT*/
107- 0x000cf3d5, /*PSET*/
108- 0x3cb45fa4, /*PUBLIC*/
109- 0x3cc0fe21, /*PUTBMP*/
110- 0x000e18d5, /*READ*/
111- 0x00015d2e, /*REM*/
112- 0x425c9703, /*RETURN*/
113- 0x00015e69, /*RND*/
114- 0x45c26d49, /*SCROLL*/
115- 0x45f6e3b3, /*SETDIR*/
116- 0x00016287, /*SGN*/
117- 0x000162cf, /*SIN*/
118- 0x000ee52d, /*SINH*/
119- 0x01f9a429, /*SOUND*/
120- 0x000f0e49, /*SQRT*/
121- 0x47f711de, /*SYSTEM*/
122- 0x000166bf, /*TAN*/
123- 0x000f72ed, /*TANH*/
124- 0x020ed5f3, /*TIMER*/
125- 0x02182fee, /*TVRAM*/
126- 0x022c2a2d, /*UNTIL*/
127- 0x4e8887d0, /*USEPCG*/
128- 0x4e88a5f3, /*USEVAR*/
129- 0x000170dd, /*VAL*/
130- 0x000170e3, /*VAR*/
131- 0x00119505, /*WAIT*/
132- 0x0011a9e9, /*WEND*/
133- 0x025aef62, /*WHILE*/
134- 0x025b8d75, /*WIDTH*/
21+ 0x0001070c, /*ABS*/
22+ 0x0002099d, /*ACOS*/
23+ 0x000258ac, /*ARGS*/
24+ 0x00010971, /*ASC*/
25+ 0x00025e4a, /*ASIN*/
26+ 0x0002627b, /*ATAN*/
27+ 0x00343bc9, /*ATAN2*/
28+ 0x004f5c95, /*BREAK*/
29+ 0x00038a2f, /*CALL*/
30+ 0x006110c1, /*CDATA*/
31+ 0x00039f24, /*CEIL*/
32+ 0x0001129b, /*CHR*/
33+ 0x0e7f3303, /*CIRCLE*/
34+ 0x0067525f, /*CLEAR*/
35+ 0x00011330, /*CLS*/
36+ 0x0069cb6b, /*COLOR*/
37+ 0x0001139f, /*COS*/
38+ 0x0003d60c, /*COSH*/
39+ 0x006bf57f, /*CREAD*/
40+ 0x0fd6b45b, /*CURSOR*/
41+ 0x00045129, /*DATA*/
42+ 0x00011776, /*DEC*/
43+ 0x122a52c0, /*DELETE*/
44+ 0x00011814, /*DIM*/
45+ 0x000100ac, /*DO*/
46+ 0x000551b8, /*ELSE*/
47+ 0x171a03a1, /*ELSEIF*/
48+ 0x00011e1d, /*END*/
49+ 0x00a20bbe, /*ENDIF*/
50+ 0x00058fdc, /*EXEC*/
51+ 0x00011f9b, /*EXP*/
52+ 0x0005da5b, /*FABS*/
53+ 0x1a358bdd, /*FCLOSE*/
54+ 0x0005f193, /*FEOF*/
55+ 0x0005fae1, /*FGET*/
56+ 0x00b94291, /*FGETC*/
57+ 0x00bacd24, /*FIELD*/
58+ 0x00060687, /*FILE*/
59+ 0x1ae2b2ef, /*FINPUT*/
60+ 0x00061598, /*FLEN*/
61+ 0x00bd52ae, /*FLOAT*/
62+ 0x00bd54b2, /*FLOOR*/
63+ 0x00061c59, /*FMOD*/
64+ 0x00bfaa2c, /*FOPEN*/
65+ 0x000123a9, /*FOR*/
66+ 0x1badd288, /*FPRINT*/
67+ 0x00062d52, /*FPUT*/
68+ 0x00c08ce6, /*FPUTC*/
69+ 0x00c286ca, /*FSEEK*/
70+ 0x0006ac5c, /*GCLS*/
71+ 0x1e59e7b7, /*GCOLOR*/
72+ 0x1e96cb44, /*GETDIR*/
73+ 0x00dc556c, /*GOSUB*/
74+ 0x0006edac, /*GOTO*/
75+ 0x1fcfed5d, /*GPRINT*/
76+ 0x00012cef, /*HEX*/
77+ 0x00083d61, /*IDLE*/
78+ 0x0001015c, /*IF*/
79+ 0x01149470, /*INKEY*/
80+ 0x0114b178, /*INPUT*/
81+ 0x00013391, /*INT*/
82+ 0x0009d063, /*KEYS*/
83+ 0x016022dc, /*LABEL*/
84+ 0x00014249, /*LEN*/
85+ 0x0001424f, /*LET*/
86+ 0x000aa9ff, /*LINE*/
87+ 0x000143b4, /*LOG*/
88+ 0x016b0db9, /*LOG10*/
89+ 0x000aca45, /*LOOP*/
90+ 0x000b8e81, /*MODF*/
91+ 0x018c8c85, /*MUSIC*/
92+ 0x000c21d6, /*NEXT*/
93+ 0x00014d04, /*NEW*/
94+ 0x00014e73, /*NOT*/
95+ 0x40e24fde, /*OPTION*/
96+ 0x0001575c, /*PCG*/
97+ 0x000daac8, /*PEEK*/
98+ 0x43be47b3, /*PEEK16*/
99+ 0x43be47f9, /*PEEK32*/
100+ 0x00010262, /*PI*/
101+ 0x01dd7f7a, /*POINT*/
102+ 0x000de11a, /*POKE*/
103+ 0x44e0c435, /*POKE16*/
104+ 0x44e0c47b, /*POKE32*/
105+ 0x00015928, /*POW*/
106+ 0x01dfd111, /*PRINT*/
107+ 0x000df5af, /*PSET*/
108+ 0x45858d00, /*PUBLIC*/
109+ 0x459341b1, /*PUTBMP*/
110+ 0x000f35e7, /*READ*/
111+ 0x0001625e, /*REM*/
112+ 0x4c0e4e9d, /*RETURN*/
113+ 0x000163a2, /*RND*/
114+ 0x4ff58ae0, /*SCROLL*/
115+ 0x50300d40, /*SETDIR*/
116+ 0x00016802, /*SGN*/
117+ 0x0001684c, /*SIN*/
118+ 0x0010130d, /*SINH*/
119+ 0x02338a69, /*SOUND*/
120+ 0x00103e75, /*SQRT*/
121+ 0x526b8f2e, /*SYSTEM*/
122+ 0x00016c7d, /*TAN*/
123+ 0x0010ae22, /*TANH*/
124+ 0x024b5425, /*TIMER*/
125+ 0x02557a82, /*TVRAM*/
126+ 0x026bf064, /*UNTIL*/
127+ 0x59f94768, /*USEPCG*/
128+ 0x59f9673f, /*USEVAR*/
129+ 0x0001772d, /*VAL*/
130+ 0x00017733, /*VAR*/
131+ 0x0012ff0c, /*WAIT*/
132+ 0x00131519, /*WEND*/
133+ 0x02a044ad, /*WHILE*/
134+ 0x02a0f0f8, /*WIDTH*/
135135 // Additional names follow
136136 ADDITIONAL_RESERVED_VAR_NAMES
137137 };
@@ -150,16 +150,18 @@ int check_var_name(){
150150 int prevpos=g_srcpos;
151151 next_position();
152152 b1=g_source[g_srcpos];
153- if (b1<'A' || 'Z'<b1) return -1;
153+ // When changing here, see also get_label()
154+ if ((b1<'A' || 'Z'<b1) && b1!='_') return -1;
154155 do {
155- // First character must be A-Z
156- // From second, A-Z and 0-9 can be used.
157- i*=36;
156+ // First character must be A-Z or _
157+ // From second, A-Z, _, and 0-9 can be used.
158+ i*=37;
159+ if (b1=='_') b1='Z'+1;
158160 if ('0'<=b1 && b1<='9') {
159161 i+=b1-'0';
160162 } else if (g_srcpos==prevpos) {
161- // First character must be A-Z.
162- // Subtract 9, resulting 1-26 but not 10-35.
163+ // First character must be A-Z or _.
164+ // Subtract 9, resulting 1-27 but not 10-36.
163165 // This subtraction is required to maintain
164166 // final number being <0x80000000.
165167 i+=b1-'A'+1;
@@ -168,7 +170,7 @@ int check_var_name(){
168170 }
169171 g_srcpos++;
170172 b1=g_source[g_srcpos];
171- } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
173+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z' || b1=='_');
172174 // Length of the label must be between 2 and 6.
173175 if (g_srcpos-prevpos<2) {
174176 // One letter var name, A-Z
--- a/mips/zoea/compiler.h
+++ b/mips/zoea/compiler.h
@@ -519,5 +519,9 @@ extern int g_int_vector[];
519519 #define div36_32(x) div32(x,0xe38e38e4,37)
520520 #define rem36_32(x) (x-36*div36_32(x))
521521
522+// Divide by 37 (valid for 31 bits)
523+#define div37_31(x) div32(x,0xdd67c8a7,37)
524+#define rem37_31(x) (x-37*div37_31(x))
525+
522526 // Check if within RAM
523527 #define withinRAM(x) ((&RAM[0])<=((char*)(x)) && ((char*)(x))<(&RAM[RAMSIZE]))
--- a/mips/zoea/debug.c
+++ b/mips/zoea/debug.c
@@ -228,14 +228,11 @@ static const char initext[]=
228228 "#PRINT\n";
229229
230230 static const char bastext[]=
231-"I=1:WHILE I<=10\n"
232-"I=I+1:WEND\n"
231+"CLS\n"
232+"LABEL TEST_:i=0/0\n"
233+"\n"
233234 "\n"
234-"I=1:DO\n"
235-"I=I+1:LOOP UNTIL I=11\n"
236235 "\n"
237-"FOR I=1 TO 10\n"
238-"NEXT\n"
239236 "\n"
240237 "\n"
241238 "\n";
--- a/mips/zoea/error.c
+++ b/mips/zoea/error.c
@@ -62,15 +62,16 @@ char* resolve_label(int s6){
6262 s6-=65536;
6363 str[6]=0x00;
6464 for(i=5;0<=i;i--){
65- if (s6<36) {
66- // First character must be A-Z, corresponding to 1-26 but not 10-35.
65+ if (s6<37) {
66+ // First character must be A-Z or _, corresponding to 1-27 but not 10-36.
6767 // See get_label() for the detail.
68- str[i]=s6-1+'A';
68+ if (s6==27) str[i]='_';
69+ else str[i]=s6-1+'A';
6970 break;
7071 } else {
71- // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
72- str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
73- s6=div36_32(s6);
72+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-36.
73+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_"[rem37_31(s6)];
74+ s6=div37_31(s6);
7475 }
7576 }
7677 return (char*)(str+i);
--- a/mips/zoea/linker.c
+++ b/mips/zoea/linker.c
@@ -44,17 +44,19 @@ char* get_label(void){
4444 g_label=0;
4545 return 0;
4646 }
47- } else if ('A'<=b1 && b1<='Z') {
47+ } else if ('A'<=b1 && b1<='Z' || b1=='_') {
4848 // May be label
49+ // When changing here, see also chech_var_name()
4950 do {
50- // First character must be A-Z
51- // From second, A-Z and 0-9 can be used.
52- i*=36;
51+ // First character must be A-Z or _
52+ // From second, A-Z, _, and 0-9 can be used.
53+ i*=37;
54+ if (b1=='_') b1='Z'+1;
5355 if ('0'<=b1 && b1<='9') {
5456 i+=b1-'0';
5557 } else if (g_srcpos==prevpos) {
56- // First character must be A-Z.
57- // Subtract 9, resulting 1-26 but not 10-35.
58+ // First character must be A-Z or _.
59+ // Subtract 9, resulting in 1-27 but not 10-36.
5860 // This subtraction is required to maintain
5961 // final number being <0x80000000.
6062 i+=b1-'A'+1;
@@ -63,7 +65,7 @@ char* get_label(void){
6365 }
6466 g_srcpos++;
6567 b1=g_source[g_srcpos];
66- } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
68+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z' || b1=='_');
6769 // Length of the label must be between 2 and 6.
6870 if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
6971 g_srcpos=prevpos;
--- a/mips/zoea/reservednames.js
+++ b/mips/zoea/reservednames.js
@@ -16,14 +16,15 @@ function name2int(name){
1616 var i=0;
1717 var b1=g_source.charCodeAt(0);
1818 do {
19- // First character must be A-Z
20- // From second, A-Z and 0-9 can be used.
21- i*=36;
19+ // First character must be A-Z or _
20+ // From second, A-Z, _, and 0-9 can be used.
21+ i*=37;
22+ if (b1=='_'.charCodeAt(0)) b1='Z'.charCodeAt(0)+1;
2223 if ('0'.charCodeAt(0)<=b1 && b1<='9'.charCodeAt(0)) {
2324 i+=b1-'0'.charCodeAt(0);
2425 } else if (g_srcpos==prevpos) {
25- // First character must be A-Z.
26- // Subtract 9, resulting 1-26 but not 10-35.
26+ // First character must be A-Z or _.
27+ // Subtract 9, resulting in 1-27 but not 10-36.
2728 // This subtraction is required to maintain
2829 // final number being <0x80000000.
2930 i+=b1-'A'.charCodeAt(0)+1;
@@ -32,10 +33,58 @@ function name2int(name){
3233 }
3334 g_srcpos++;
3435 b1=g_source.charCodeAt(g_srcpos);
35- } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
36+ } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || b1=='_'.charCodeAt(0) ||
37+ 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
3638 return i+65536;
3739 }
3840
41+function int2name(s6){
42+ var rem37_31=function(s6){
43+ return s6 % 37;
44+ };
45+ var div37_31=function(s6){
46+ return (s6-(s6 % 37))/37;
47+ };
48+ var str=new Array();
49+ var i,res;
50+ s6-=65536;
51+ str[6]=0;
52+ for(i=5;0<=i;i--){
53+ if (s6<37) {
54+ // First character must be A-Z or _, corresponding to 1-27 but not 10-36.
55+ // See get_label() for the detail.
56+ if (s6==27) str[i]='_'.charCodeAt(0);
57+ else str[i]=s6-1+'A'.charCodeAt(0);
58+ break;
59+ } else {
60+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-36.
61+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charCodeAt(rem37_31(s6));
62+ s6=div37_31(s6);
63+ }
64+ }
65+ //return (char*)(str+i);
66+ for(res='';str[i];i++) {
67+ res+=String.fromCharCode(str[i]);
68+ }
69+ return res;
70+}
71+
72+// Show max number by this system.
73+//WScript.Echo(name2int('______').toString(16));
74+
75+// Test functions for 10000 times with randomized var names
76+for(i=0;i<10000;i++){
77+ t="ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charAt(Math.random()*27);
78+ for(j=0;j<1+Math.random()*4;j++){
79+ t+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_".charAt(Math.random()*37);
80+ }
81+ j=name2int(t);
82+ if (int2name(j)!=t || j<0 || 0x7fffffff<j) {
83+ WScript.Echo('ERROR: '+t+' ('+j+'; 0x'+j.toString(16)+') '+i);
84+ WScript.Quit();
85+ }
86+}
87+
3988 var namearray=[
4089 'ABS',
4190 'ACOS',
@@ -168,14 +217,16 @@ var namearray=[
168217 'I2C',
169218 ];
170219 var result='';
220+var commented=0;
171221 for(key in namearray){
172222 var nameint='0000'+name2int(namearray[key]).toString(16);
173223 nameint=nameint.substr(nameint.length-8);
174224 if (namearray[key].substr(0,2)=='//') {
175225 // This is a comment
176226 result+=namearray[key]+"\r\n";
227+ commented=1;
177228 } else {
178- result+="\t0x"+nameint+", /*"+namearray[key]+"*/\r\n";
229+ result+="\t0x"+nameint+", /*"+namearray[key]+"*/"+(commented ? " \\\r\n" : "\r\n");
179230 }
180231 }
181232
--- a/mips/zoea/statement.c
+++ b/mips/zoea/statement.c
@@ -313,7 +313,7 @@ char* label_statement(){
313313 char* err;
314314 char b1;
315315 b1=g_source[g_srcpos];
316- if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
316+ if ('0'<=b1 && b1<='9') return ERR_SYNTAX; // Number is not allowed here.
317317 err=get_label();
318318 if (err) return err;
319319 // Check existing label with the same name here.
--- a/mips/zoea/varname.c
+++ b/mips/zoea/varname.c
@@ -18,120 +18,120 @@
1818 */
1919
2020 static const int reserved_var_names[]={
21- 0x000106b8, /*ABS*/
22- 0x0001f67c, /*ACOS*/
23- 0x0002414c, /*ARGS*/
24- 0x0001090c, /*ASC*/
25- 0x0002469f, /*ASIN*/
26- 0x00024a8f, /*ATAN*/
27- 0x002f7c1e, /*ATAN2*/
28- 0x0047c31c, /*BREAK*/
29- 0x00035869, /*CALL*/
30- 0x00575afe, /*CDATA*/
31- 0x00036c3d, /*CEIL*/
32- 0x000111af, /*CHR*/
33- 0x0cb1b682, /*CIRCLE*/
34- 0x005d1ea3, /*CLEAR*/
35- 0x00011240, /*CLS*/
36- 0x005f66cb, /*COLOR*/
37- 0x000112ac, /*COS*/
38- 0x0003a041, /*COSH*/
39- 0x00616415, /*CREAD*/
40- 0x0de593fb, /*CURSOR*/
41- 0x00040fbe, /*DATA*/
42- 0x00011644, /*DEC*/
43- 0x0fe19c42, /*DELETE*/
44- 0x000116de, /*DIM*/
45- 0x000100a8, /*DO*/
46- 0x0004fd8e, /*ELSE*/
47- 0x1434a177, /*ELSEIF*/
48- 0x00011c99, /*END*/
49- 0x0091c927, /*ENDIF*/
50- 0x00053854, /*EXEC*/
51- 0x00011e0d, /*EXP*/
52- 0x000579c8, /*FABS*/
53- 0x16e3d4be, /*FCLOSE*/
54- 0x00058fcf, /*FEOF*/
55- 0x00059895, /*FGET*/
56- 0x00a67500, /*FGETC*/
57- 0x00a7e061, /*FIELD*/
58- 0x0005a3a2, /*FILE*/
59- 0x177f0ca5, /*FINPUT*/
60- 0x0005b1df, /*FLEN*/
61- 0x00aa3445, /*FLOAT*/
62- 0x00aa363b, /*FLOOR*/
63- 0x0005b84d, /*FMOD*/
64- 0x00ac5c9f, /*FOPEN*/
65- 0x000121db, /*FOR*/
66- 0x18352839, /*FPRINT*/
67- 0x0005c865, /*FPUT*/
68- 0x00ad2e40, /*FPUTC*/
69- 0x00aefdec, /*FSEEK*/
70- 0x00063b90, /*GCLS*/
71- 0x1a808bcb, /*GCOLOR*/
72- 0x1ab733b3, /*GETDIR*/
73- 0x00c60f03, /*GOSUB*/
74- 0x0006796c, /*GOTO*/
75- 0x1bcfcc39, /*GPRINT*/
76- 0x00012a99, /*HEX*/
77- 0x0007ad12, /*IDLE*/
78- 0x00010153, /*IF*/
79- 0x00f8701a, /*INKEY*/
80- 0x00f88ba5, /*INPUT*/
81- 0x000130e9, /*INT*/
82- 0x00092084, /*KEYS*/
83- 0x013be43d, /*LABEL*/
84- 0x00013ecf, /*LEN*/
85- 0x00013ed5, /*LET*/
86- 0x0009e96a, /*LINE*/
87- 0x00014030, /*LOG*/
88- 0x0145f324, /*LOG10*/
89- 0x000a07f9, /*LOOP*/
90- 0x000abca3, /*MODF*/
91- 0x016418d4, /*MUSIC*/
92- 0x000b4321, /*NEXT*/
93- 0x000148f8, /*NEW*/
94- 0x00014a5d, /*NOT*/
95- 0x38a658d7, /*OPTION*/
96- 0x000152c0, /*PCG*/
97- 0x000cacec, /*PEEK*/
98- 0x3b1c6aea, /*PEEK16*/
99- 0x3b1c6b2e, /*PEEK32*/
100- 0x00010252, /*PI*/
101- 0x01ac8479, /*POINT*/
102- 0x000ce05e, /*POKE*/
103- 0x3c20dc0a, /*POKE16*/
104- 0x3c20dc4e, /*POKE32*/
105- 0x00015480, /*POW*/
106- 0x01aea739, /*PRINT*/
107- 0x000cf3d5, /*PSET*/
108- 0x3cb45fa4, /*PUBLIC*/
109- 0x3cc0fe21, /*PUTBMP*/
110- 0x000e18d5, /*READ*/
111- 0x00015d2e, /*REM*/
112- 0x425c9703, /*RETURN*/
113- 0x00015e69, /*RND*/
114- 0x45c26d49, /*SCROLL*/
115- 0x45f6e3b3, /*SETDIR*/
116- 0x00016287, /*SGN*/
117- 0x000162cf, /*SIN*/
118- 0x000ee52d, /*SINH*/
119- 0x01f9a429, /*SOUND*/
120- 0x000f0e49, /*SQRT*/
121- 0x47f711de, /*SYSTEM*/
122- 0x000166bf, /*TAN*/
123- 0x000f72ed, /*TANH*/
124- 0x020ed5f3, /*TIMER*/
125- 0x02182fee, /*TVRAM*/
126- 0x022c2a2d, /*UNTIL*/
127- 0x4e8887d0, /*USEPCG*/
128- 0x4e88a5f3, /*USEVAR*/
129- 0x000170dd, /*VAL*/
130- 0x000170e3, /*VAR*/
131- 0x00119505, /*WAIT*/
132- 0x0011a9e9, /*WEND*/
133- 0x025aef62, /*WHILE*/
134- 0x025b8d75, /*WIDTH*/
21+ 0x0001070c, /*ABS*/
22+ 0x0002099d, /*ACOS*/
23+ 0x000258ac, /*ARGS*/
24+ 0x00010971, /*ASC*/
25+ 0x00025e4a, /*ASIN*/
26+ 0x0002627b, /*ATAN*/
27+ 0x00343bc9, /*ATAN2*/
28+ 0x004f5c95, /*BREAK*/
29+ 0x00038a2f, /*CALL*/
30+ 0x006110c1, /*CDATA*/
31+ 0x00039f24, /*CEIL*/
32+ 0x0001129b, /*CHR*/
33+ 0x0e7f3303, /*CIRCLE*/
34+ 0x0067525f, /*CLEAR*/
35+ 0x00011330, /*CLS*/
36+ 0x0069cb6b, /*COLOR*/
37+ 0x0001139f, /*COS*/
38+ 0x0003d60c, /*COSH*/
39+ 0x006bf57f, /*CREAD*/
40+ 0x0fd6b45b, /*CURSOR*/
41+ 0x00045129, /*DATA*/
42+ 0x00011776, /*DEC*/
43+ 0x122a52c0, /*DELETE*/
44+ 0x00011814, /*DIM*/
45+ 0x000100ac, /*DO*/
46+ 0x000551b8, /*ELSE*/
47+ 0x171a03a1, /*ELSEIF*/
48+ 0x00011e1d, /*END*/
49+ 0x00a20bbe, /*ENDIF*/
50+ 0x00058fdc, /*EXEC*/
51+ 0x00011f9b, /*EXP*/
52+ 0x0005da5b, /*FABS*/
53+ 0x1a358bdd, /*FCLOSE*/
54+ 0x0005f193, /*FEOF*/
55+ 0x0005fae1, /*FGET*/
56+ 0x00b94291, /*FGETC*/
57+ 0x00bacd24, /*FIELD*/
58+ 0x00060687, /*FILE*/
59+ 0x1ae2b2ef, /*FINPUT*/
60+ 0x00061598, /*FLEN*/
61+ 0x00bd52ae, /*FLOAT*/
62+ 0x00bd54b2, /*FLOOR*/
63+ 0x00061c59, /*FMOD*/
64+ 0x00bfaa2c, /*FOPEN*/
65+ 0x000123a9, /*FOR*/
66+ 0x1badd288, /*FPRINT*/
67+ 0x00062d52, /*FPUT*/
68+ 0x00c08ce6, /*FPUTC*/
69+ 0x00c286ca, /*FSEEK*/
70+ 0x0006ac5c, /*GCLS*/
71+ 0x1e59e7b7, /*GCOLOR*/
72+ 0x1e96cb44, /*GETDIR*/
73+ 0x00dc556c, /*GOSUB*/
74+ 0x0006edac, /*GOTO*/
75+ 0x1fcfed5d, /*GPRINT*/
76+ 0x00012cef, /*HEX*/
77+ 0x00083d61, /*IDLE*/
78+ 0x0001015c, /*IF*/
79+ 0x01149470, /*INKEY*/
80+ 0x0114b178, /*INPUT*/
81+ 0x00013391, /*INT*/
82+ 0x0009d063, /*KEYS*/
83+ 0x016022dc, /*LABEL*/
84+ 0x00014249, /*LEN*/
85+ 0x0001424f, /*LET*/
86+ 0x000aa9ff, /*LINE*/
87+ 0x000143b4, /*LOG*/
88+ 0x016b0db9, /*LOG10*/
89+ 0x000aca45, /*LOOP*/
90+ 0x000b8e81, /*MODF*/
91+ 0x018c8c85, /*MUSIC*/
92+ 0x000c21d6, /*NEXT*/
93+ 0x00014d04, /*NEW*/
94+ 0x00014e73, /*NOT*/
95+ 0x40e24fde, /*OPTION*/
96+ 0x0001575c, /*PCG*/
97+ 0x000daac8, /*PEEK*/
98+ 0x43be47b3, /*PEEK16*/
99+ 0x43be47f9, /*PEEK32*/
100+ 0x00010262, /*PI*/
101+ 0x01dd7f7a, /*POINT*/
102+ 0x000de11a, /*POKE*/
103+ 0x44e0c435, /*POKE16*/
104+ 0x44e0c47b, /*POKE32*/
105+ 0x00015928, /*POW*/
106+ 0x01dfd111, /*PRINT*/
107+ 0x000df5af, /*PSET*/
108+ 0x45858d00, /*PUBLIC*/
109+ 0x459341b1, /*PUTBMP*/
110+ 0x000f35e7, /*READ*/
111+ 0x0001625e, /*REM*/
112+ 0x4c0e4e9d, /*RETURN*/
113+ 0x000163a2, /*RND*/
114+ 0x4ff58ae0, /*SCROLL*/
115+ 0x50300d40, /*SETDIR*/
116+ 0x00016802, /*SGN*/
117+ 0x0001684c, /*SIN*/
118+ 0x0010130d, /*SINH*/
119+ 0x02338a69, /*SOUND*/
120+ 0x00103e75, /*SQRT*/
121+ 0x526b8f2e, /*SYSTEM*/
122+ 0x00016c7d, /*TAN*/
123+ 0x0010ae22, /*TANH*/
124+ 0x024b5425, /*TIMER*/
125+ 0x02557a82, /*TVRAM*/
126+ 0x026bf064, /*UNTIL*/
127+ 0x59f94768, /*USEPCG*/
128+ 0x59f9673f, /*USEVAR*/
129+ 0x0001772d, /*VAL*/
130+ 0x00017733, /*VAR*/
131+ 0x0012ff0c, /*WAIT*/
132+ 0x00131519, /*WEND*/
133+ 0x02a044ad, /*WHILE*/
134+ 0x02a0f0f8, /*WIDTH*/
135135 // Additional names follow
136136 ADDITIONAL_RESERVED_VAR_NAMES
137137 };
@@ -150,16 +150,18 @@ int check_var_name(){
150150 int prevpos=g_srcpos;
151151 next_position();
152152 b1=g_source[g_srcpos];
153- if (b1<'A' || 'Z'<b1) return -1;
153+ // When changing here, see also get_label()
154+ if ((b1<'A' || 'Z'<b1) && b1!='_') return -1;
154155 do {
155- // First character must be A-Z
156- // From second, A-Z and 0-9 can be used.
157- i*=36;
156+ // First character must be A-Z or _
157+ // From second, A-Z, _, and 0-9 can be used.
158+ i*=37;
159+ if (b1=='_') b1='Z'+1;
158160 if ('0'<=b1 && b1<='9') {
159161 i+=b1-'0';
160162 } else if (g_srcpos==prevpos) {
161- // First character must be A-Z.
162- // Subtract 9, resulting 1-26 but not 10-35.
163+ // First character must be A-Z or _.
164+ // Subtract 9, resulting 1-27 but not 10-36.
163165 // This subtraction is required to maintain
164166 // final number being <0x80000000.
165167 i+=b1-'A'+1;
@@ -168,7 +170,7 @@ int check_var_name(){
168170 }
169171 g_srcpos++;
170172 b1=g_source[g_srcpos];
171- } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
173+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z' || b1=='_');
172174 // Length of the label must be between 2 and 6.
173175 if (g_srcpos-prevpos<2) {
174176 // One letter var name, A-Z