diff options
Diffstat (limited to 'pu2')
| -rw-r--r-- | pu2/code.i2 | 19 | ||||
| -rw-r--r-- | pu2/pu2.c | 273 |
2 files changed, 222 insertions, 70 deletions
diff --git a/pu2/code.i2 b/pu2/code.i2 index c42cdd5..06d1c54 100644 --- a/pu2/code.i2 +++ b/pu2/code.i2 @@ -1,3 +1,11 @@ +/* + + testing grounds for the ir2 assembler + i still don't know whether it's a compiler, an IR emitter, or an assembler + hmmm... + +*/ + macro puts(2) { @1 = 0; // write @2 = /1/; // ptr @@ -13,13 +21,12 @@ macro putchar(1) { system(); } -@10 = 1; +@10 = 0; -jz(@10, continue); // conditional jump! - -puts(["hi"], [2]); - -continue: +// if statement!! +if (@10) { + puts(["hi"], [2]); +} putchar([10]); puts([" hello world"], [15]); @@ -229,7 +229,7 @@ clean_slice_ref(slice_t *val) { free(val->ref); } }) #define scanword() \ ({ \ - slice_t VAR = { 0, I }; \ + slice_t VAR = { 0, I }; \ while (isalnum(*I) || *I == '_') VAR.len++, I++; \ VAR; \ }) @@ -270,11 +270,11 @@ clean_slice_ref(slice_t *val) { free(val->ref); } }) // #define emit(OP, VAL) (*Code++ = (OP), *Code++ = (VAL)) -#define store() (emit(opcode.acc, 1), emit(opcode.str, 0)) +#define store() (emit(opcode.acc, 1), op(str)) #define op(mode) emit(opcode.mode, 0) -#define swap() emit(opcode.swp, 0) +#define swap() op(swp) #define imm(value) emit(opcode.imm, value) -#define load() emit(opcode.lod, 0) +#define load() op(lod) #define imm_in_mem(__mem, __imm) (imm(__mem), emit(opcode.cb3, __imm)) #define mov_mem_mem(__mem1, __mem2) (imm(__mem1), emit(opcode.cb4, __mem2)) #define mem_in_a(__mem) emit(opcode.cb2, __mem) @@ -283,13 +283,12 @@ clean_slice_ref(slice_t *val) { free(val->ref); } mem_in_a(mem2_index); \ swap(); \ mem_in_a(mem_index); \ - emit(opcode.operation, 0); \ + op(operation); \ swap(); \ imm(mem_index); \ store(); \ }) -char T; string ERR; string ERR_code; int *Code; @@ -305,28 +304,86 @@ __attribute__((always_inline)) emit(int op, int val) { *Code++ = val; } +int ir2_depth = 0; + +#define space skip_space(&I) + bool has_jump_warned = false; -_ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delegated_t forward_refs[ 1 << 10 ]) { +bool has_useless_if_warned = false; + +string _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delegated_t forward_refs[ 1 << 10 ]) { + char T; string init_I = I; ERR = "all good"; while (T = *I) { - skip_space(&I); + if (isspace(T)) { + space; + continue; + } + + string start_I = I; - if (T == '/' && I[ 1 ] == '/') { // comment + if (T == '}') { + if (ir2_depth == 0) run_err(I, "unexpected closing bracket"); + ir2_depth--; + + return ++I; + } + + else if (T == '/' && I[ 1 ] == '/') { // comment I += 2; while (*I != '\n' && *I != '\0') I++; + continue; + } + + else if (T == '/' && I[1] == '*') { // multi-line comment + string old_I = I; + I+= 2; + while (*I != '*' || I[1] != '/') { + if (I[1] == '\0') { + run_err(old_I, "reached EOF whilst looking for closing comment delimeter"); + } + + I++; + } + I += 2; + continue; } // handle assignments! - if (T == '@') { + else if (T == '@') { I++; + if (!isdigit(*I)) { run_err(I, "expected a digit after @"); } int mem_index = strtol(I, &I, 10); - skip_space(&I); + space; + + if(*I == '-' && I[1] == '-') { // decrement + I += 2; + space; + checkskip(';', "expected semicolon"); + imm(1); + swap(); + mem_in_a(mem_index); + op(sub); + store(); + } + + if(*I == '+' && I[1] == '+') { // increment + I += 2; + space; + checkskip(';', "expected semicolon"); + imm(1); + swap(); + mem_in_a(mem_index); + op(add); + store(); + } + char extra_op = '='; if (*I == '+' || *I == '-' || *I == '&' || *I == '!') extra_op = *I++; checkskip('=', "expected assigment after memory blob (hint: only +-&! are supported)"); - skip_space(&I); + space; if (mem_index == 7 && !has_jump_warned) { has_jump_warned = true; @@ -351,7 +408,7 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega } else if (extra_op == '!') { // @1 != @2; mem_in_a(mem2_index); - emit(opcode.not, 0); + op(not); swap(); imm(mem_index); store(); @@ -365,7 +422,7 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega imm(imm); swap(); mem_in_a(mem_index); - emit(opcode.add, 0); + op(add); swap(); imm(mem_index); store(); @@ -373,45 +430,46 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega imm(imm); swap(); mem_in_a(mem_index); - emit(opcode.sub, 0); + op(sub); store(); } else if (extra_op == '&') { imm(imm); swap(); mem_in_a(mem_index); - emit(opcode.and, 0); + op(and); store(); } else if (extra_op == '!') { // @1 != 5; imm(imm); - emit(opcode.not, 0); + op(not); swap(); imm(mem_index); store(); } } - skip_space(&I); + space; checkskip(';', "expected semicolon"); continue; } // register macros - if (strncmp("macro", I, 5) == 0 && isspace(I[ 5 ])) { + else if (strncmp("macro", I, 5) == 0 && isspace(I[ 5 ])) { I += 6; - skip_space(&I); + space; // parse macro stuff if (!isalpha(*I) && *I != '_') { run_err(I - 1, "expected letter or underscore at macro name"); } + string old_I = I; slice_t name = scanword(); - skip_space(&I); + space; checkskip('(', "expected open paren in macro defintion"); - skip_space(&I); + space; string before = I; int arg_count = strtol(I, &I, 10); @@ -419,14 +477,14 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega run_err(I, "expected number (argument count) in macro definition parens"); } - skip_space(&I); + space; checkskip( ')', "expected close paren in macro definition (hint: macro defintions only take an " "argument count)"); - skip_space(&I); + space; checkskip('{', "expected open curly bracket in macro body"); @@ -434,14 +492,17 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega int x; for (x = 0; x < (1 << 9); x++) { macro_t g = macros[ x ]; - if (g.data.key.ref == NULL) { goto DONE; } + if (g.data.key.ref == NULL) goto DONE; + if (g.data.key.len == name.len && strncmp(g.data.key.ref, name.ref, name.len) == 0) { + run_err(old_I, "redefinition of macro"); + } } run_err(I - 1, "registered macro count exceeded 1<<9 (how?)"); DONE:; - skip_space(&I); // might aswell skip whitespace for funsies. + space; // might aswell skip whitespace for funsies. macro_t *g = ¯os[ x ]; g->data.key = name; g->data.value.ref = I; @@ -465,7 +526,7 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega } // emit exit calls - if (strncmp("exit", I, 4) == 0) { + else if (strncmp("exit", I, 4) == 0) { I += 4; checkskip('(', "expected open paren on exit blob"); @@ -475,53 +536,52 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega run_err(I - 1, "invalid input to exit blob, expected number"); } - skip_space(&I); + space; checkskip(')', "expected open paren on exit blob"); - skip_space(&I); + space; checkskip(';', "expected semicolon after call"); // actually emit stuff if (old != I) emit(opcode.imm, value); - emit(opcode.hlt, 0); + op(hlt); continue; } // emit system - if (strncmp("system", I, 6) == 0 && !isalnum(I[ 6 ])) { + else if (strncmp("system", I, 6) == 0 && !isalnum(I[ 6 ])) { I += 6; - skip_space(&I); + space; checkskip('(', "expected open paren on system blob"); - skip_space(&I); + space; checkskip( ')', "expected closing paren on system blob (hint: system does not take any arguments)"); - skip_space(&I); + space; checkskip(';', "expected semicolon after system blob"); imm_in_mem(0, 2); - emit(opcode.hlt, 0); + op(hlt); continue; } - if (strncmp("jump", I, 4) == 0 && !isalnum(I[4])) { + else if (strncmp("jump", I, 4) == 0 && !isalnum(I[4])) { I += 4; goto PARSE_JUMP_BLOB; } - if (strncmp("jmp", I, 3) == 0 && !isalnum(I[3])) { + else if (strncmp("jmp", I, 3) == 0 && !isalnum(I[3])) { I += 3; PARSE_JUMP_BLOB: - skip_space(&I); + space; checkskip('(', "expected open paren on jump blob"); - skip_space(&I); + space; if(!isalpha(*I)) run_err(I, "expected a label name for jump blob argument"); - slice_t label = { 1, I }; - while (isalnum(*++I)) label.len++; - skip_space(&I); + slice_t label = scanword(); + space; checkskip(')', "expected closing paren after label name in jump blob"); - skip_space(&I); + space; checkskip(';', "excpected semicolon after jump blob"); // resolve right now if the label exists @@ -557,31 +617,31 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega del->name = label; del->init_I = init_I; - FINISH_JMP:; + FINISH_JMP: + continue; } - if ((strncmp("jnz", I, 3) == 0 && !isalnum(I[3])) || (strncmp("jz", I, 2) == 0 && !isalnum(I[2]))) { + else if ((strncmp("jnz", I, 3) == 0 && !isalnum(I[3])) || (strncmp("jz", I, 2) == 0 && !isalnum(I[2]))) { bool was_jnz = !!strncmp("jz", I, 2); string name = was_jnz ? "jnz" : "jz"; I += was_jnz ? 3 : 2; - skip_space(&I); + space; checkskip('(', "expected open paren on %s blob", name); - skip_space(&I); + space; checkskip('@', "expected memory address format as first %s argument (example: `%s(@5, label_name);`)", name, name); int target_mem = strtol(I, &I, 10); - skip_space(&I); + space; checkskip(',', "expected comma (second argument) in %s blob (example: `%s(@5, label_name);`)", name, name); - skip_space(&I); + space; if(!isalpha(*I)) run_err(I, "expected a label name for %s blob's second argument (example: `%s(@5, label_name);`)", name, name); - slice_t label = { 1, I }; - while (isalnum(*++I)) label.len++; - skip_space(&I); + slice_t label = scanword(); + space; checkskip(')', "expected closing paren after label name in %s blob (do i really need to explain this to you again?)", name); - skip_space(&I); + space; checkskip(';', "excpected semicolon after %s blob", name); // resolve right now if the label exists @@ -620,7 +680,7 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega WRITE_DEL_JNZ: - // emit jnz + // emit j(n)z mem_in_a(target_mem); if (!was_jnz) op(not); op(a2u); @@ -633,13 +693,87 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega del->name = label; del->init_I = init_I; - FINISH_JNZ:; + FINISH_JNZ: + continue; + } + + else if (strncmp("if", I, 2) == 0 && !isalnum(I[2])) { + // if statement + I += 2; + space; checkskip('(', "expected open paren for if statement"); space; + + ir2_depth++; + + if (isdigit(*I)) { + if (!has_useless_if_warned) { + has_useless_if_warned = true; + printf("warn: redundant if statement\n"); + } + + // redundant if statement: always true / always false + int value = strtol(I, &I, 10); space; + checkskip(')', "expected closing paren after if statement argument"); space; + checkskip('{', "expected opening bracket for if statement body"); space; + + if (!value) { + // just skip over everything inside + + int *Code_B = Code; + int *Data_B = Data; + + // get new I location + string new_I = _ir2(I, macros, labels, forward_refs); + I = new_I; + // restore values + Code = Code_B; + Data = Data_B; + + continue; + } + + else { + // just... i mean, i guess run the code..? + string new_I = _ir2(I, macros, labels, forward_refs); + I = new_I; + continue; + } + } + + bool was_negated = false; + if (*I == '!') { + was_negated = true; + I++; space; + } + + checkskip('@', "expected memory address for if statement expression (hint: only simple if statements are supported)"); + if (!isdigit(*I)) run_err(I, "expected memory index"); + int mem_index = strtol(I, &I, 10); space; + checkskip(')', "expected closing paren after if statement argument"); space; + checkskip('{', "expected opening bracket for if statement body"); space; + + mem_in_a(mem_index); + if (!was_negated) op(not); + op(a2u); + imm(0xDEAD10C4); // DEADLOCK - placeholder for the patchback + int* patchback = Code - 1; + swap(); + imm(7); + op(str); + + // handle the code stuff + string new_I = _ir2(I, macros, labels, forward_refs); + I = new_I; + + *patchback = Code - m; // patch the jump instruction + + continue; } // macro call, maybe? - if (isalpha(*I)) { + else if (isalpha(*I)) { + string old_I = I; slice_t name = scanword(); - skip_space(&I); + space; if(*I == ':') { I++; @@ -647,12 +781,18 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega label_t *slot; int j; for (j = 0; j < 1 << 10; j++) { - if (labels[j].name.ref != NULL) continue; + if (labels[j].name.ref != NULL) { + if (labels[j].name.len == name.len && strncmp(labels[j].name.ref, name.ref, name.len) == 0) { + run_err(old_I, "redefinition of label"); + } + continue; + } + slot = &labels[j]; goto FOUND_SLOT; } - run_err(I - 1, "registered label count exceeded 1<<10 (how?)"); + run_err(old_I, "registered label count exceeded 1<<10 (how?)"); FOUND_SLOT: slot->name = name; @@ -662,7 +802,7 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega } checkskip('(', "expected open paren after alphanumeric word (assuming this is a blob)"); - skip_space(&I); + space; slice_t arguments[ 1 << 7 ]; size_t arg_count = 0; @@ -689,17 +829,17 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega } } - skip_space(&I); + space; checkskip(']', "expected closing bracket in macro arguments"); - skip_space(&I); + space; if (*I != ',' && *I != ')') { run_err(I, "expected comma or closing paren in blob"); } if (*I == ',') { I++; - skip_space(&I); + space; } arg_count++; @@ -708,7 +848,7 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega fail_I = I; checkskip(')', "expected closing paren after blob arguments"); - skip_space(&I); + space; checkskip(';', "expected semicolon after blob"); // done reading blob! check it and parse macro :) @@ -785,7 +925,12 @@ _ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delega continue; } + + // unknown + else run_err(I, "unknown token '%c' (%i)", T, T); } + + return I; } ir2(string I) { |
