BASIC compiler/interpreter for PIC32MX/MZ-80K (suspended)
Révision | 272 (tree) |
---|---|
l'heure | 2018-10-20 04:35:42 |
Auteur | kmorimatsu |
Allow including class file(s).
@@ -0,0 +1,151 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +#include "compiler.h" | |
9 | + | |
10 | +static int* g_class_structure; | |
11 | + | |
12 | +/* | |
13 | + CMPDATA_CLASS structure | |
14 | + type: CMPDATA_CLASS (2) | |
15 | + len: 3 | |
16 | + data16: n/a (0) | |
17 | + record[1]: class name as integer | |
18 | + record[2]: pointer to class structure | |
19 | +*/ | |
20 | + | |
21 | +/* | |
22 | + CMPDATA_FIELD structure | |
23 | + type: CMPDATA_FIELD (3) | |
24 | + len: 2 or 3 (2: field; 3: method) | |
25 | + data16: field or method | |
26 | + 0: public field | |
27 | + 1: private field | |
28 | + 2: public method | |
29 | + 3: reserved | |
30 | + record[1]: field/method name as integer | |
31 | + record[2]: pointer to method | |
32 | +*/ | |
33 | + | |
34 | +#define PUBLIC_FIELD 0 | |
35 | +#define PRIVATE_FIELD 1 | |
36 | +#define PUBLIC_METHOD 2 | |
37 | + | |
38 | +char* update_class_info(int class){ | |
39 | + int* record; | |
40 | + int data[2]; | |
41 | + // Update record if exist. | |
42 | + cmpdata_reset(); | |
43 | + while(record=cmpdata_find(CMPDATA_CLASS)){ | |
44 | + if (record[1]==class) { | |
45 | + record[2]=(int)g_class_structure; | |
46 | + return 0; | |
47 | + } | |
48 | + } | |
49 | + // No record of this class yet. Insert a record. | |
50 | + data[0]=class; | |
51 | + data[1]=(int)g_class_structure; | |
52 | + return cmpdata_insert(CMPDATA_CLASS,0,&data[0],2); | |
53 | +} | |
54 | + | |
55 | +/* | |
56 | + Class structure: | |
57 | + cstruct[0]: class name as integer | |
58 | + cstruct[1]: number of fields and methods: | |
59 | + bit 0-7: # of public fields | |
60 | + bit 8-15: # of private fields | |
61 | + bit 16-23: # of public methods | |
62 | + bit 24-31: reserved | |
63 | + cstruct[x]: public fields name | |
64 | + cstruct[y]: private fields name | |
65 | + cstruct[z], cstruct[z+1]: public methods name and pointer | |
66 | +*/ | |
67 | + | |
68 | +char* construct_class_structure(int class){ | |
69 | + int num; | |
70 | + int* record; | |
71 | + // Register current address to global var | |
72 | + g_class_structure=&g_object[g_objpos]; | |
73 | + // Construct a class structure in object area in following lines | |
74 | + // Class name | |
75 | + check_obj_space(2); | |
76 | + g_object[g_objpos++]=class; // Class name | |
77 | + g_objpos++; // Number of fields/methods | |
78 | + // Public fields | |
79 | + cmpdata_reset(); | |
80 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
81 | + if (record[0]&0xffff==PUBLIC_FIELD) { | |
82 | + num+=1<<0; | |
83 | + check_obj_space(1); | |
84 | + g_object[g_objpos++]=record[1]; | |
85 | + } | |
86 | + } | |
87 | + // Private fields | |
88 | + cmpdata_reset(); | |
89 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
90 | + if (record[0]&0xffff==PRIVATE_FIELD) { | |
91 | + num+=1<<8; | |
92 | + check_obj_space(1); | |
93 | + g_object[g_objpos++]=record[1]; | |
94 | + } | |
95 | + } | |
96 | + // Public methods | |
97 | + cmpdata_reset(); | |
98 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
99 | + if (record[0]&0xffff==PUBLIC_METHOD) { | |
100 | + num+=1<<16; | |
101 | + check_obj_space(2); | |
102 | + g_object[g_objpos++]=record[1]; | |
103 | + g_object[g_objpos++]=record[2]; | |
104 | + } | |
105 | + } | |
106 | + // Update number info | |
107 | + g_class_structure[1]=num; | |
108 | + return 0; | |
109 | +} | |
110 | + | |
111 | +void delete_cmpdata_for_class(){ | |
112 | + int* record; | |
113 | + // Delete field/method data | |
114 | + cmpdata_reset(); | |
115 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
116 | + cmpdata_delete(record); | |
117 | + } | |
118 | + // Delete longvar data | |
119 | + cmpdata_reset(); | |
120 | + while(record=cmpdata_find(CMPDATA_USEVAR)){ | |
121 | + cmpdata_delete(record); | |
122 | + } | |
123 | +} | |
124 | + | |
125 | +void construct_class_list(){ | |
126 | + int* record; | |
127 | + int pclass; | |
128 | + int num; | |
129 | + // Initialize | |
130 | + cmpdata_reset(); | |
131 | + num=0; | |
132 | + g_classlist=&g_object[g_objpos]; | |
133 | + // List up classes | |
134 | + while(record=cmpdata_find(CMPDATA_CLASS)){ | |
135 | + num++; | |
136 | + pclass=record[2]; | |
137 | + // Delete CMPDATA, first | |
138 | + cmpdata_delete(record); | |
139 | + // There must be area because a CMPDATA was deleted above | |
140 | + g_object[g_objpos++]=pclass; | |
141 | + } | |
142 | + if (num) { | |
143 | + // Show the number of classes used. | |
144 | + printstr(" Using "); | |
145 | + printnum(num); | |
146 | + printstr(" classes. "); | |
147 | + } else { | |
148 | + // Disable class list | |
149 | + g_classlist=0; | |
150 | + } | |
151 | +} |
@@ -84,3 +84,21 @@ | ||
84 | 84 | cmpdata_reset(); |
85 | 85 | return cmpdata_find(type); |
86 | 86 | } |
87 | + | |
88 | +/* | |
89 | + Delete a record. | |
90 | +*/ | |
91 | +void cmpdata_delete(int* record){ | |
92 | + int delnum; | |
93 | + int* data; | |
94 | + // Ignore if invalid record. | |
95 | + if (record<g_cmpdata || g_cmpdata_end<record) return; | |
96 | + // Get number of word to delete. | |
97 | + delnum=(record[0]&0x00ff0000)>>16; | |
98 | + // Delete record by shifting data. | |
99 | + for(data=record-1;g_cmpdata<=data;data--){ | |
100 | + data[delnum]=data[0]; | |
101 | + } | |
102 | + // Reset | |
103 | + cmpdata_reset(); | |
104 | +} |
@@ -213,6 +213,8 @@ | ||
213 | 213 | extern unsigned short* g_graphic_area; |
214 | 214 | extern int* g_libparams; |
215 | 215 | extern int g_long_name_var_num; |
216 | +extern int g_class; | |
217 | +extern int* g_classlist; | |
216 | 218 | extern int g_temp; |
217 | 219 | |
218 | 220 | /* Prototypes */ |
@@ -228,6 +230,8 @@ | ||
228 | 230 | void close_file(); |
229 | 231 | void read_file(int blocklen); |
230 | 232 | char* compile_file(); |
233 | +int compile_and_link_file(char* buff,char* appname); | |
234 | +int compile_and_link_class(char* buff,int class); | |
231 | 235 | |
232 | 236 | void err_break(void); |
233 | 237 | void err_music(char* str); |
@@ -305,6 +309,7 @@ | ||
305 | 309 | void cmpdata_reset(); |
306 | 310 | int* cmpdata_find(unsigned char type); |
307 | 311 | int* cmpdata_findfirst(unsigned char type); |
312 | +void cmpdata_delete(int* record); | |
308 | 313 | |
309 | 314 | int check_var_name(); |
310 | 315 | int get_var_number(); |
@@ -311,6 +316,9 @@ | ||
311 | 316 | int search_var_name(int nameint); |
312 | 317 | char* register_var_name(int nameint); |
313 | 318 | |
319 | +char* update_class_info(int class); | |
320 | +char* construct_class_structure(int class); | |
321 | +void delete_cmpdata_for_class(); | |
314 | 322 | |
315 | 323 | /* Error messages */ |
316 | 324 | #define ERR_SYNTAX (char*)(g_err_str[0]) |
@@ -335,10 +343,13 @@ | ||
335 | 343 | #define ERR_FILE (char*)(g_err_str[19]) |
336 | 344 | #define ERR_INVALID_VAR_NAME (char*)(g_err_str[20]) |
337 | 345 | #define ERR_WAVE (char*)(g_err_str[21]) |
346 | +#define ERR_COMPILE_CLASS (char*)(g_err_str[22]) | |
338 | 347 | |
339 | 348 | /* comple data type numbers */ |
340 | 349 | #define CMPDATA_RESERVED 0 |
341 | 350 | #define CMPDATA_USEVAR 1 |
351 | +#define CMPDATA_CLASS 2 | |
352 | +#define CMPDATA_FIELD 3 | |
342 | 353 | |
343 | 354 | /* Macros */ |
344 | 355 |
@@ -32,6 +32,7 @@ | ||
32 | 32 | |
33 | 33 | static const char initext[]; |
34 | 34 | static const char bastext[]; |
35 | +static const char classtext[]; | |
35 | 36 | |
36 | 37 | static char* readtext; |
37 | 38 | static int filepos; |
@@ -130,7 +131,12 @@ | ||
130 | 131 | readtext=(char*)&initext[0]; |
131 | 132 | } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') { |
132 | 133 | // BAS file |
133 | - readtext=(char*)&bastext[0]; | |
134 | + if (fileName[i-6]=='C' && fileName[i-5]=='L' && fileName[i-4]=='A' && | |
135 | + fileName[i-3]=='S' && fileName[i-2]=='S' && fileName[i-1]=='1') { | |
136 | + readtext=(char*)&classtext[0]; | |
137 | + } else { | |
138 | + readtext=(char*)&bastext[0]; | |
139 | + } | |
134 | 140 | // Try debugDump. |
135 | 141 | if (debugDump()) return 0; |
136 | 142 | } else { |
@@ -221,9 +227,14 @@ | ||
221 | 227 | |
222 | 228 | static const char bastext[]= |
223 | 229 | "CLS\n" |
224 | -"print NOT(0);IN(0)\n" | |
230 | +"useclass class1\n" | |
225 | 231 | "\n"; |
226 | 232 | |
233 | +static const char classtext[]= | |
234 | +"REM\n" | |
235 | +"print \"CLASS1\"\n" | |
236 | +"\n"; | |
237 | + | |
227 | 238 | /* |
228 | 239 | Test function for constructing assemblies from C codes. |
229 | 240 | */ |
@@ -30,6 +30,7 @@ | ||
30 | 30 | "File error", |
31 | 31 | "Invalid variable name", |
32 | 32 | "WAVE format error", |
33 | + "ERR_COMPILE_CLASS", | |
33 | 34 | }; |
34 | 35 | |
35 | 36 | char* resolve_label(int s6){ |
@@ -19,9 +19,12 @@ | ||
19 | 19 | if (!g_fhandle) { |
20 | 20 | return ERR_UNKNOWN; |
21 | 21 | } |
22 | + // Initialize parameters | |
22 | 23 | g_fbuff=buff; |
23 | 24 | g_line=0; |
24 | 25 | g_fileline=0; |
26 | + g_source=buff; | |
27 | + g_srcpos=0; | |
25 | 28 | return 0; |
26 | 29 | } |
27 | 30 |
@@ -97,3 +100,104 @@ | ||
97 | 100 | return 0; |
98 | 101 | } |
99 | 102 | |
103 | +int compile_and_link_file(char* buff,char* appname){ | |
104 | + int i; | |
105 | + char* err; | |
106 | + | |
107 | + while(1){ | |
108 | + // Initialize SD card file system | |
109 | + err=init_file(buff,appname); | |
110 | + if (err) { | |
111 | + //setcursorcolor(COLOR_ERRORTEXT); | |
112 | + printstr("Can't Open "); | |
113 | + printstr(appname); | |
114 | + printchar('\n'); | |
115 | + return -1; | |
116 | + } | |
117 | + | |
118 | + // Compile the file | |
119 | + err=compile_file(); | |
120 | + close_file(); | |
121 | + | |
122 | + // If compiling a class file is required, do it. | |
123 | + if (err==ERR_COMPILE_CLASS) { | |
124 | + i=compile_and_link_class(buff, g_class); | |
125 | + if (i) return i; | |
126 | + // Continue compiling current file from the beginning. | |
127 | + continue; | |
128 | + } | |
129 | + break; | |
130 | + } | |
131 | + | |
132 | + if (err) { | |
133 | + // Compile error | |
134 | + printstr(err); | |
135 | + printstr("\nAround: '"); | |
136 | + for(i=0;i<5;i++){ | |
137 | + printchar(g_source[g_srcpos-2+i]); | |
138 | + } | |
139 | + printstr("' in line "); | |
140 | + printdec(g_line); | |
141 | + printstr("\n"); | |
142 | + for(i=g_srcpos;0x20<=g_source[i];i++); | |
143 | + g_source[i]=0x00; | |
144 | + for(i=g_srcpos;0x20<=g_source[i];i--); | |
145 | + printstr(g_source+i); | |
146 | + return g_fileline; | |
147 | + } | |
148 | + | |
149 | + // Link | |
150 | + err=link(); | |
151 | + if (err) { | |
152 | + // Link error | |
153 | + printstr(err); | |
154 | + printstr(resolve_label(g_label)); | |
155 | + return -2; | |
156 | + } | |
157 | + | |
158 | + // All done | |
159 | + return 0; | |
160 | +} | |
161 | + | |
162 | +int compile_and_link_class(char* buff,int class){ | |
163 | + int i; | |
164 | + char* err; | |
165 | + char* classname; | |
166 | + char classfile[13]; | |
167 | + int data[2]; | |
168 | + while(1){ | |
169 | + // Register the class to cmpdata | |
170 | + err=update_class_info(class); | |
171 | + if (err) break; | |
172 | + // Determine class file name | |
173 | + classname=resolve_label(class); | |
174 | + for(i=0;classfile[i]=classname[i];i++); | |
175 | + classfile[i++]='.'; | |
176 | + classfile[i++]='B'; | |
177 | + classfile[i++]='A'; | |
178 | + classfile[i++]='S'; | |
179 | + classfile[i]=0; | |
180 | + // Compile it | |
181 | + i=compile_and_link_file(buff,&classfile[0]); | |
182 | + if (i) break; | |
183 | + // Construct class structure | |
184 | + err=construct_class_structure(class); | |
185 | + if (err) break; | |
186 | + // Uppdate class information. | |
187 | + err=update_class_info(class); | |
188 | + if (err) break; | |
189 | + // Delete some cmpdata. | |
190 | + delete_cmpdata_for_class(); | |
191 | + // In the next link, current region of object is ignored. | |
192 | + g_object+=g_objpos; | |
193 | + g_objpos=0; | |
194 | + // All done | |
195 | + return 0; | |
196 | + } | |
197 | + // Error occured | |
198 | + printstr("/nError in class: "); | |
199 | + printstr((char*)&classfile[0]); | |
200 | + printchar('\n'); | |
201 | + if (err) printstr(err); | |
202 | + return -2; | |
203 | +} | |
\ No newline at end of file |
@@ -75,5 +75,10 @@ | ||
75 | 75 | // Number of long name variables |
76 | 76 | int g_long_name_var_num; |
77 | 77 | |
78 | +// Class name being compiled | |
79 | +int g_class; | |
80 | +// Pointer to lass list | |
81 | +int* g_classlist; | |
82 | + | |
78 | 83 | // General purpose integer used for asigning value with pointer |
79 | 84 | int g_temp; |
@@ -44,10 +44,8 @@ | ||
44 | 44 | |
45 | 45 | // Set grobal pointer |
46 | 46 | g_gp=get_gp(); |
47 | - // Set source positions | |
47 | + // Set buffer positions | |
48 | 48 | buff=(char*)&(RAM[RAMSIZE-512]); |
49 | - g_source=(char*)(&buff[0]); | |
50 | - g_srcpos=0; | |
51 | 49 | // Set object positions |
52 | 50 | g_object=(int*)(&RAM[0]); |
53 | 51 | g_objpos=0; |
@@ -54,7 +52,8 @@ | ||
54 | 52 | g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded. |
55 | 53 | // Clear object area |
56 | 54 | for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000; |
57 | - // Initialize SD card file system | |
55 | + | |
56 | + // Check file error | |
58 | 57 | err=init_file(buff,appname); |
59 | 58 | if (err) { |
60 | 59 | setcursorcolor(COLOR_ERRORTEXT); |
@@ -63,6 +62,7 @@ | ||
63 | 62 | printchar('\n'); |
64 | 63 | return -1; |
65 | 64 | } |
65 | + close_file(); | |
66 | 66 | |
67 | 67 | // Initialize parameters |
68 | 68 | g_pcg_font=0; |
@@ -82,34 +82,9 @@ | ||
82 | 82 | printstr("Compiling..."); |
83 | 83 | |
84 | 84 | // Compile the file |
85 | - err=compile_file(); | |
86 | - close_file(); | |
87 | - if (err) { | |
88 | - // Compile error | |
89 | - printstr(err); | |
90 | - printstr("\nAround: '"); | |
91 | - for(i=0;i<5;i++){ | |
92 | - printchar(g_source[g_srcpos-2+i]); | |
93 | - } | |
94 | - printstr("' in line "); | |
95 | - printdec(g_line); | |
96 | - printstr("\n"); | |
97 | - for(i=g_srcpos;0x20<=g_source[i];i++); | |
98 | - g_source[i]=0x00; | |
99 | - for(i=g_srcpos;0x20<=g_source[i];i--); | |
100 | - printstr(g_source+i); | |
101 | - return g_fileline; | |
102 | - } | |
85 | + i=compile_and_link_file(buff,appname); | |
86 | + if (i) return i; | |
103 | 87 | |
104 | - // Link | |
105 | - err=link(); | |
106 | - if (err) { | |
107 | - // Link error | |
108 | - printstr(err); | |
109 | - printstr(resolve_label(g_label)); | |
110 | - return -2; | |
111 | - } | |
112 | - | |
113 | 88 | // All done |
114 | 89 | printstr("done\n"); |
115 | 90 | if(test) return 0; //コンパイルのみの場合 |
@@ -1469,6 +1469,39 @@ | ||
1469 | 1469 | return 0; |
1470 | 1470 | } |
1471 | 1471 | |
1472 | +char* useclass_statement(){ | |
1473 | + char* err; | |
1474 | + int i; | |
1475 | + int* cmpdata; | |
1476 | + do { | |
1477 | + next_position(); | |
1478 | + i=check_var_name(); | |
1479 | + if (i<65536) return ERR_SYNTAX; | |
1480 | + // Check if the class already exists | |
1481 | + cmpdata_reset(); | |
1482 | + while(cmpdata=cmpdata_find(CMPDATA_CLASS)){ | |
1483 | + if (cmpdata[1]==i) { | |
1484 | + // The class was already defined. | |
1485 | + i=0; | |
1486 | + break; | |
1487 | + } | |
1488 | + } | |
1489 | + if (i) { | |
1490 | + // Remove a objects before USECLASS statement | |
1491 | + g_objpos=0; | |
1492 | + // Load new file to define class statement. | |
1493 | + g_class=i; | |
1494 | + return ERR_COMPILE_CLASS; | |
1495 | + } | |
1496 | + if (g_source[g_srcpos]==',') { | |
1497 | + g_srcpos++; | |
1498 | + } else { | |
1499 | + break; | |
1500 | + } | |
1501 | + } while(1); | |
1502 | + return 0; | |
1503 | +} | |
1504 | + | |
1472 | 1505 | #ifdef __DEBUG |
1473 | 1506 | char* debug_statement(){ |
1474 | 1507 | call_lib_code(LIB_DEBUG); |
@@ -1596,6 +1629,7 @@ | ||
1596 | 1629 | "FREMOVE ",fremove_statement, |
1597 | 1630 | "USEVAR ",usevar_statement, |
1598 | 1631 | "PLAYWAVE ",playwave_statement, |
1632 | + "USECLASS ",useclass_statement, | |
1599 | 1633 | // List of additional statements follows |
1600 | 1634 | ADDITIONAL_STATEMENTS |
1601 | 1635 | }; |