5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is furnished to do
10 * so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * This is the assembler, gmqas, this is being implemented because I'm
26 * not exactly sure how codegen would work for the C compiler as of yet
27 * and also I plan to allow inline assembly for the compiler.
29 static const char *const asm_instr[] = {
30 [INSTR_DONE] = "DONE",
31 [INSTR_MUL_F] = "MUL_F",
32 [INSTR_MUL_V] = "MUL_V",
33 [INSTR_MUL_FV] = "MUL_FV",
34 [INSTR_MUL_VF] = "MUL_VF",
35 [INSTR_DIV_F] = "DIV",
36 [INSTR_ADD_F] = "ADD_F",
37 [INSTR_ADD_V] = "ADD_V",
38 [INSTR_SUB_F] = "SUB_F",
39 [INSTR_SUB_V] = "DUB_V",
40 [INSTR_EQ_F] = "EQ_F",
41 [INSTR_EQ_V] = "EQ_V",
42 [INSTR_EQ_S] = "EQ_S",
43 [INSTR_EQ_E] = "EQ_E",
44 [INSTR_EQ_FNC] = "ES_FNC",
45 [INSTR_NE_F] = "NE_F",
46 [INSTR_NE_V] = "NE_V",
47 [INSTR_NE_S] = "NE_S",
48 [INSTR_NE_E] = "NE_E",
49 [INSTR_NE_FNC] = "NE_FNC",
54 [INSTR_LOAD_F] = "FIELD_F",
55 [INSTR_LOAD_V] = "FIELD_V",
56 [INSTR_LOAD_S] = "FIELD_S",
57 [INSTR_LOAD_ENT] = "FIELD_ENT",
58 [INSTR_LOAD_FLD] = "FIELD_FLD",
59 [INSTR_LOAD_FNC] = "FIELD_FNC",
60 [INSTR_ADDRESS] = "ADDRESS",
61 [INSTR_STORE_F] = "STORE_F",
62 [INSTR_STORE_V] = "STORE_V",
63 [INSTR_STORE_S] = "STORE_S",
64 [INSTR_STORE_ENT] = "STORE_ENT",
65 [INSTR_STORE_FLD] = "STORE_FLD",
66 [INSTR_STORE_FNC] = "STORE_FNC",
67 [INSTR_STOREP_F] = "STOREP_F",
68 [INSTR_STOREP_V] = "STOREP_V",
69 [INSTR_STOREP_S] = "STOREP_S",
70 [INSTR_STOREP_ENT] = "STOREP_ENT",
71 [INSTR_STOREP_FLD] = "STOREP_FLD",
72 [INSTR_STOREP_FNC] = "STOREP_FNC",
73 [INSTR_RETURN] = "RETURN",
74 [INSTR_NOT_F] = "NOT_F",
75 [INSTR_NOT_V] = "NOT_V",
76 [INSTR_NOT_S] = "NOT_S",
77 [INSTR_NOT_ENT] = "NOT_ENT",
78 [INSTR_NOT_FNC] = "NOT_FNC",
80 [INSTR_IFNOT] = "IFNOT",
81 [INSTR_CALL0] = "CALL0",
82 [INSTR_CALL1] = "CALL1",
83 [INSTR_CALL2] = "CALL2",
84 [INSTR_CALL3] = "CALL3",
85 [INSTR_CALL4] = "CALL4",
86 [INSTR_CALL5] = "CALL5",
87 [INSTR_CALL6] = "CALL6",
88 [INSTR_CALL7] = "CALL7",
89 [INSTR_CALL8] = "CALL8",
90 [INSTR_STATE] = "STATE",
91 [INSTR_GOTO] = "GOTO",
94 [INSTR_BITAND] = "AND",
99 * Some assembler keywords not part of the opcodes above: these are
100 * for creating functions, or constants.
102 const char *const asm_keys[] = {
103 "FLOAT" , /* define float */
104 "VECTOR" , /* define vector */
105 "ENTITY" , /* define ent */
106 "FIELD" , /* define field */
107 "STRING" , /* define string */
111 static char *const asm_getline(size_t *byte, FILE *fp) {
113 ssize_t read = getline(&line, byte, fp);
123 #define asm_rmnewline(L,S) *((L)+*(S)-1) = '\0'
124 #define asm_skipwhite(L) \
125 while((*(L)==' '||*(L)=='\t')) { \
129 void asm_init(const char *file, FILE **fp) {
130 *fp = fopen(file, "r");
134 void asm_close(FILE *fp) {
139 void asm_parse(FILE *fp) {
142 long line = 1; /* current line */
143 size_t size = 0; /* size of line */
145 while ((data = asm_getline(&size, fp)) != NULL) {
148 asm_rmnewline(skip, &size);
150 #define DECLTYPE(X, CODE) \
151 if (!strncmp(X, skip, strlen(X))) { \
152 if (skip[strlen(X)] != ':') { \
153 printf("%li: Missing `:` after decltype\n",line); \
156 skip += strlen(X)+1; \
157 asm_skipwhite(skip); \
158 if(!isalpha(*skip)) { \
159 printf("%li: Invalid identififer: %s\n", line, skip); \
162 size_t offset_code = code_statements_elements+1; \
163 size_t offset_chars = code_strings_elements +1; \
164 size_t offset_globals = code_globals_elements +1; \
165 size_t offset_functions = code_functions_elements +1; \
166 size_t offset_fields = code_fields_elements +1; \
167 size_t offset_defs = code_defs_elements +1; \
169 /* silent unused warnings */ \
171 (void)offset_chars; \
172 (void)offset_globals; \
173 (void)offset_functions; \
174 (void)offset_fields; \
181 DECLTYPE(asm_keys[0], {
182 code_defs_add((prog_section_def){
184 .offset = offset_globals, /* global table */
185 .name = offset_chars /* string table TODO */
187 float f = 0; /*TODO*/
188 code_globals_add(*(int*)&f);
191 DECLTYPE(asm_keys[1], {
192 code_defs_add((prog_section_def){
194 .offset = offset_globals, /* global table */
195 .name = offset_chars /* string table TODO */
200 code_globals_add(*(int*)&f1);
201 code_globals_add(*(int*)&f2);
202 code_globals_add(*(int*)&f3);
204 /* ENTITY */ DECLTYPE(asm_keys[2], {});
205 /* FIELD */ DECLTYPE(asm_keys[3], {});
207 DECLTYPE(asm_keys[4], {
208 code_defs_add((prog_section_def){
210 .offset = offset_globals, /* offset to offset in string table (for data)*/
211 .name = offset_chars /* location of name in string table (for name)*/
214 /* FUNCTION */ DECLTYPE(asm_keys[5], {});
216 /* if we make it this far then we have statements */
219 for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
220 if (!strncmp(skip, asm_instr[i], strlen(asm_instr[i]))) {
227 /* if we made it this far something is wrong */