diff --git a/src/tools/compiler/compiler.c b/src/tools/compiler/compiler.c index 93db49b..f421376 100644 --- a/src/tools/compiler/compiler.c +++ b/src/tools/compiler/compiler.c @@ -13,14 +13,23 @@ void emit_op(VM *vm, u8 byte) { +#ifdef DEBUG_PRINT + printf("code[%d] = %s\n", vm->cp, opcode_to_string(byte)); +#endif vm->code[vm->cp] = byte; } void emit_byte(VM *vm, u8 byte) { +#ifdef DEBUG_PRINT + printf("code[%d] = %d\n", vm->cp, byte); +#endif vm->code[vm->cp] = byte; } void emit_u32(VM *vm, u32 value) { +#ifdef DEBUG_PRINT + printf("code[%d..%d] = %d\n", vm->cp, vm->cp + 3, value); +#endif write_u32(vm, code, vm->cp, value); } @@ -50,8 +59,7 @@ u8 symbol_table_add(ScopeTable *table, Symbol s) { exit(1); } - u8 current_index = table->scopes[table->scope_ref].count; - if (current_index + 1 > 255) { + if (table->scopes[table->scope_ref].count + 1 > 255) { fprintf(stderr, "Error: Only 255 symbols are allowed per scope" " first off: impressive; secondly:" " just create a new scope and keep going.\n"); @@ -68,11 +76,7 @@ u8 symbol_table_add(ScopeTable *table, Symbol s) { table->count, table->capacity); exit(1); } - - /* set ref to current count for local */ - s.ref = current_index; - -#ifdef DEBUG_COMPILER +#ifdef DEBUG_PRINT if (s.scope == VAR) { printf("$%d = %s\n", s.ref, s.name); } else if (s.scope == GLOBAL) { @@ -81,10 +85,10 @@ u8 symbol_table_add(ScopeTable *table, Symbol s) { printf("code[%d] = %s\n", s.ref, s.name); } #endif - - table->scopes[table->scope_ref].symbols[current_index] = s; + table->scopes[table->scope_ref].symbols[table->scopes[table->scope_ref].count] = s; + u8 index = table->scopes[table->scope_ref].count; table->scopes[table->scope_ref].count++; - return current_index; + return index; } u32 get_ref(ScopeTable *st, const char *name, u32 length) { @@ -98,6 +102,76 @@ u32 get_ref(ScopeTable *st, const char *name, u32 length) { return sym->ref; } +u32 get_ptr(Token token, ScopeTable *st) { + if (token.type == TOKEN_IDENTIFIER) { + return get_ref(st, token.start, token.length); + } + + if (token.type == TOKEN_LITERAL_INT) { + return atoi(token.start); + } + + if (token.type == TOKEN_LITERAL_NAT) { + char *endptr; + u32 out = (u32)strtoul(token.start, &endptr, 10); + if (endptr == token.start || *endptr != '\0') { + fprintf(stderr, "Invalid decimal literal at line %d: %.*s\n", token.line, + token.length, token.start); + exit(1); + } + return out; + } + + fprintf(stderr, "Error: Not a pointer or symbol at line %d: %.*s\n", + token.line, token.length, token.start); + exit(1); +} + +u32 get_reg(Token token, ScopeTable *st) { + if (token.type == TOKEN_IDENTIFIER) { + return get_ref(st, token.start, token.length); + } + + if (token.type == TOKEN_BIG_MONEY) { + token = next_token(); + return atoi(token.start); + } + + fprintf(stderr, "Error: Not a register or symbol at line %d: %.*s\n", + token.line, token.length, token.start); + exit(1); +} + +Token next_id_or_reg() { + Token token = next_token(); + if (token.type == TOKEN_IDENTIFIER) { + return token; + } + + if (token.type == TOKEN_BIG_MONEY) { + token = next_token(); + return token; + } + + printf("Not an ID or register at line %d: %.*s\n", token.line, token.length, + token.start); + exit(1); + + return token; +} + +Token next_id_or_ptr() { + Token token = next_token(); + + if (token.type != TOKEN_IDENTIFIER && token.type != TOKEN_LITERAL_NAT && + token.type != TOKEN_LITERAL_INT && token.type != TOKEN_LITERAL_REAL) { + printf("Not an ID or register at line %d: %.*s\n", token.line, token.length, + token.start); + exit(1); + } + return token; +} + Token next_token_is(TokenType type) { Token token = next_token(); if (token.type != type) { @@ -107,12 +181,188 @@ Token next_token_is(TokenType type) { return token; } +/** + * Const . + */ +bool parse_const(VM *vm, ScopeTable *st) { + return true; +} + +/** + * Global . + */ +bool define_global(VM *vm, ScopeTable *st) { + Symbol s; + + Token token_type = next_token(); + switch (token_type.type) { + case TOKEN_TYPE_BOOL: + s.type = BOOL; + s.size = 1; + break; + case TOKEN_TYPE_I8: + s.type = I8; + s.size = 1; + break; + case TOKEN_TYPE_U8: + s.type = U8; + s.size = 1; + break; + case TOKEN_TYPE_I16: + s.type = I16; + s.size = 2; + break; + case TOKEN_TYPE_U16: + s.type = U16; + s.size = 2; + break; + case TOKEN_TYPE_INT: + s.type = I32; + s.size = 4; + break; + case TOKEN_TYPE_NAT: + s.type = U32; + s.size = 4; + break; + case TOKEN_TYPE_REAL: + s.type = F32; + s.size = 4; + break; + case TOKEN_TYPE_STR: + s.type = STR; + break; + case TOKEN_IDENTIFIER: + break; + default: + return false; + } + + Token name = next_token_is(TOKEN_IDENTIFIER); + if (name.length > MAX_SYMBOL_NAME_LENGTH) { + return false; + } + + memcpy(s.name, name.start, name.length); + s.name_length = name.length; + s.name[name.length] = '\0'; + + u32 addr = vm->mp; + s.ref = addr; + s.scope = GLOBAL; + + next_token_is(TOKEN_EQ); + + Token value = next_token(); + switch (value.type) { + case TOKEN_KEYWORD_TRUE: { + u32 addr = vm->mp; + write_u8(vm, memory, addr, 1); + + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; + break; + } + case TOKEN_KEYWORD_FALSE: { + u32 addr = vm->mp; + write_u8(vm, memory, addr, 0); + + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; + break; + } + case TOKEN_LITERAL_INT: { + i32 out = atoi(value.start); + + u32 addr = vm->mp; + write_u32(vm, memory, addr, out); + + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; + break; + } + case TOKEN_LITERAL_NAT: { + char *endptr; + u32 out = (u32)strtoul(value.start, &endptr, 10); + if (endptr == value.start || *endptr != '\0') { + fprintf(stderr, "Invalid decimal literal: %s\n", value.start); + exit(1); + } + + u32 addr = vm->mp; + write_u32(vm, memory, addr, out); + + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; + break; + } + case TOKEN_LITERAL_REAL: { + r32 out = float_to_real(atof(value.start)); + + u32 addr = vm->mp; + write_u32(vm, memory, addr, out); + + vm->mp += s.size; + vm->frames[vm->fp].end += s.size; + break; + } + case TOKEN_LITERAL_STR: { + const char *src = value.start; + i32 len = 0; + i32 i = 0; + + while (i < value.length) { + char c = src[i++]; + if (c == '"') { + continue; + } + if (c == '\\' && i < value.length) { + switch (src[i++]) { + case 'n': + c = '\n'; + break; + case 't': + c = '\t'; + break; + case 'r': + c = '\r'; + break; + case '\\': + case '"': + case '\'': + break; + default: + i--; /* Rewind for unknown escapes */ + } + } + write_u8(vm, memory, addr + 4 + len, c); + len++; + } + + u32 size = len + 5; /* 4 (len) + dst_len + 1 (null) */ + s.size = size; + + vm->mp += size; + vm->frames[vm->fp].end += size; + + write_u32(vm, memory, addr, len); + write_u8(vm, memory, addr + 4 + len, '\0'); + break; + } + default: + return false; + } + next_token_is(TOKEN_SEMICOLON); + + symbol_table_add(st, s); + return true; +} + /** * Var . */ void define_var(ScopeTable *st, Token regType) { Symbol s; - s.scope = (st->depth) ? VAR : GLOBAL; + s.scope = VAR; switch (regType.type) { case TOKEN_KEYWORD_PLEX: { s.type = PLEX; @@ -181,6 +431,17 @@ void define_var(ScopeTable *st, Token regType) { s.name[name.length] = '\0'; s.name_length = name.length; + Token next = next_token(); + if (next.type == TOKEN_BIG_MONEY) { + Token reg_num = next_token_is(TOKEN_LITERAL_INT); + s.ref = atoi(reg_num.start); + } else if (next.type == TOKEN_SEMICOLON) { + s.ref = st->scopes[st->scope_ref].count; + } else { + printf("Unexpected token ERROR at line %d: %.*s\n", regType.line, regType.length, + regType.start); + exit(1); + } symbol_table_add(st, s); } @@ -189,12 +450,12 @@ void define_var(ScopeTable *st, Token regType) { * Plex . */ void define_plex(VM *vm, ScopeTable *st) { - + } /** - * Function . + * function . */ void define_function(VM *vm, ScopeTable *st) { Symbol s; @@ -286,42 +547,30 @@ int get_instruction_byte_size(const char *opname) { strcmp(opname, "store_indirect_16") == 0 || strcmp(opname, "real_to_int") == 0 || strcmp(opname, "store_indirect_32") == 0 || - strcmp(opname, "real_to_nat") == 0 || - strcmp(opname, "nat_to_int") == 0 || + strcmp(opname, "real_to_nat") == 0 || strcmp(opname, "nat_to_int") == 0 || strcmp(opname, "int_to_nat") == 0 || - strcmp(opname, "string_length") == 0 || - strcmp(opname, "memset") == 0 || - strcmp(opname, "memset") == 0 || - strcmp(opname, "memset_8") == 0 || + strcmp(opname, "string_length") == 0 || strcmp(opname, "memset") == 0 || + strcmp(opname, "memset") == 0 || strcmp(opname, "memset_8") == 0 || strcmp(opname, "memset_16") == 0 || - strcmp(opname, "register_move") == 0 || - strcmp(opname, "malloc") == 0) { + strcmp(opname, "register_move") == 0 || strcmp(opname, "malloc") == 0) { return 3; } - if (strcmp(opname, "add_int") == 0 || - strcmp(opname, "sub_int") == 0 || - strcmp(opname, "mul_int") == 0 || - strcmp(opname, "div_int") == 0 || - strcmp(opname, "add_nat") == 0 || - strcmp(opname, "sub_nat") == 0 || - strcmp(opname, "mul_nat") == 0 || - strcmp(opname, "div_nat") == 0 || - strcmp(opname, "add_real") == 0 || - strcmp(opname, "sub_real") == 0 || - strcmp(opname, "mul_real") == 0 || - strcmp(opname, "div_real") == 0 || + if (strcmp(opname, "add_int") == 0 || strcmp(opname, "sub_int") == 0 || + strcmp(opname, "mul_int") == 0 || strcmp(opname, "div_int") == 0 || + strcmp(opname, "add_nat") == 0 || strcmp(opname, "sub_nat") == 0 || + strcmp(opname, "mul_nat") == 0 || strcmp(opname, "div_nat") == 0 || + strcmp(opname, "add_real") == 0 || strcmp(opname, "sub_real") == 0 || strcmp(opname, "bit_shift_left") == 0 || strcmp(opname, "bit_shift_right") == 0 || strcmp(opname, "bit_shift_r_ext") == 0 || - strcmp(opname, "bit_and") == 0 || - strcmp(opname, "bit_or") == 0 || - strcmp(opname, "bit_xor") == 0) { + strcmp(opname, "bit_and") == 0 || strcmp(opname, "bit_or") == 0 || + strcmp(opname, "bit_xor") == 0 || strcmp(opname, "mul_real") == 0 || + strcmp(opname, "div_real") == 0) { return 4; } - if (strcmp(opname, "halt") == 0 || - strcmp(opname, "jump_if_flag") == 0 || + if (strcmp(opname, "halt") == 0 || strcmp(opname, "jump_if_flag") == 0 || strcmp(opname, "jump") == 0) { return 5; } @@ -368,6 +617,18 @@ int get_instruction_byte_size(const char *opname) { exit(-1); } +#define FAKE_OP(op) \ + } else if (strleq(token.start, op, token.length)) { \ + do { \ + while (token.type != TOKEN_SEMICOLON) { \ + token = next_token(); \ + } \ + /*printf("code[%d]=%s\n %d + %d = %d\n", vm->cp, op, \ + * get_instruction_byte_size(op), vm->cp, vm->cp + \ + * get_instruction_byte_size(op)); */ \ + vm->cp += get_instruction_byte_size(op); \ + } while (0); + /** * Build the symbol table and calculate the types/size/offsets of all values. */ @@ -396,7 +657,7 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { i32 parent = st->scopes[current_scope].parent; if (parent < 0) parent = 0; st->scope_ref = parent; - st->depth--; + st->depth--; continue; } @@ -410,24 +671,22 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { continue; } - if (token.type == TOKEN_TYPE_I8 || - token.type == TOKEN_TYPE_I16 || - token.type == TOKEN_TYPE_INT || - token.type == TOKEN_TYPE_U8 || - token.type == TOKEN_TYPE_U16 || - token.type == TOKEN_TYPE_NAT || - token.type == TOKEN_TYPE_REAL || - token.type == TOKEN_TYPE_STR || - token.type == TOKEN_TYPE_BOOL) { - define_var(st, token); - next_token_is(TOKEN_SEMICOLON); + if (token.type == TOKEN_TYPE_PTR || token.type == TOKEN_TYPE_I8 || + token.type == TOKEN_TYPE_I16 || token.type == TOKEN_TYPE_INT || + token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || + token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || + token.type == TOKEN_TYPE_STR || token.type == TOKEN_TYPE_BOOL) { + if (st->depth > 0) { + define_var(st, token); + next_token_is(TOKEN_SEMICOLON); + } else { + define_global(vm, st); + } continue; } - if (token.type == TOKEN_KEYWORD_LOOP || - token.type == TOKEN_KEYWORD_IF || - token.type == TOKEN_KEYWORD_ELSE || - token.type == TOKEN_KEYWORD_DO || + if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || + token.type == TOKEN_KEYWORD_ELSE || token.type == TOKEN_KEYWORD_DO || token.type == TOKEN_KEYWORD_FOR) { define_branch(vm, st); continue; @@ -443,7 +702,7 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { continue; } - get_ref(st, next.start, next.length); + get_reg(next, st); vm->cp++; next_token_is(TOKEN_SEMICOLON); continue; @@ -454,7 +713,148 @@ void build_symbol_table(VM *vm, char *source, ScopeTable *st) { #endif if (token.type == TOKEN_IDENTIFIER) { /* check to see if it is an opcode first */ - if (false) { + if (strleq(token.start, "exit", token.length)) { + + vm->cp++; + + next_token(); + vm->cp += 4; + +#ifdef DEBUG_PRINT + printf("code[%d] = exit\n", vm->cp); +#endif + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "call", token.length)) { + + vm->cp++; + + next_token_is(TOKEN_IDENTIFIER); + vm->cp += 4; + + vm->cp++; + Token next = next_token_is(TOKEN_LPAREN); + next = next_token(); + while (next.type != TOKEN_RPAREN) { + get_reg(next, st); + vm->cp++; + next = next_token(); + } + + next = next_token(); + if (next.type == TOKEN_SEMICOLON) { + vm->cp++; + } else { + next = next_token(); + get_reg(next, st); + vm->cp++; + } +#ifdef DEBUG_PRINT + printf("code[%d] = call\n", vm->cp); +#endif + continue; + } else if (strleq(token.start, "syscall", token.length)) { + + vm->cp++; + + Token next = next_token(); + vm->cp += 4; + + next = next_token(); + while (next.type != TOKEN_SEMICOLON) { + get_reg(next, st); + vm->cp++; + next = next_token(); + } +#ifdef DEBUG_PRINT + printf("code[%d] = syscall\n", vm->cp); +#endif + continue; + FAKE_OP("load_immediate") + FAKE_OP("load_address") + FAKE_OP("malloc") + FAKE_OP("memset_8") + FAKE_OP("memset_16") + FAKE_OP("memset_32") + FAKE_OP("load_offset_8") + FAKE_OP("load_offset_16") + FAKE_OP("load_offset_32") + FAKE_OP("load_indirect_8") + FAKE_OP("load_indirect_16") + FAKE_OP("load_indirect_32") + FAKE_OP("load_absolute_8") + FAKE_OP("load_absolute_16") + FAKE_OP("load_absolute_32") + FAKE_OP("store_absolute_8") + FAKE_OP("store_absolute_16") + FAKE_OP("store_absolute_32") + FAKE_OP("store_indirect_8") + FAKE_OP("store_indirect_16") + FAKE_OP("store_indirect_32") + FAKE_OP("store_offset_8") + FAKE_OP("store_offset_16") + FAKE_OP("store_offset_32") + FAKE_OP("register_move") + FAKE_OP("add_int") + FAKE_OP("sub_int") + FAKE_OP("mul_int") + FAKE_OP("div_int") + FAKE_OP("abs_int") + FAKE_OP("neg_int") + FAKE_OP("add_nat") + FAKE_OP("sub_nat") + FAKE_OP("mul_nat") + FAKE_OP("div_nat") + FAKE_OP("abs_nat") + FAKE_OP("neg_nat") + FAKE_OP("add_real") + FAKE_OP("sub_real") + FAKE_OP("mul_real") + FAKE_OP("div_real") + FAKE_OP("abs_real") + FAKE_OP("neg_real") + FAKE_OP("int_to_real") + FAKE_OP("nat_to_real") + FAKE_OP("real_to_int") + FAKE_OP("real_to_nat") + FAKE_OP("bit_shift_left") + FAKE_OP("bit_shift_right") + FAKE_OP("bit_shift_r_ext") + FAKE_OP("bit_and") + FAKE_OP("bit_or") + FAKE_OP("bit_xor") + FAKE_OP("jump") + FAKE_OP("jump_if_flag") + FAKE_OP("jump_eq_int") + FAKE_OP("jump_neq_int") + FAKE_OP("jump_gt_int") + FAKE_OP("jump_lt_int") + FAKE_OP("jump_le_int") + FAKE_OP("jump_ge_int") + FAKE_OP("jump_eq_nat") + FAKE_OP("jump_neq_nat") + FAKE_OP("jump_gt_nat") + FAKE_OP("jump_lt_nat") + FAKE_OP("jump_le_nat") + FAKE_OP("jump_ge_nat") + FAKE_OP("jump_eq_real") + FAKE_OP("jump_neq_real") + FAKE_OP("jump_ge_real") + FAKE_OP("jump_gt_real") + FAKE_OP("jump_lt_real") + FAKE_OP("jump_le_real") + FAKE_OP("string_length") + FAKE_OP("int_to_string") + FAKE_OP("nat_to_string") + FAKE_OP("real_to_string") + FAKE_OP("string_eq") + FAKE_OP("string_concat") + FAKE_OP("string_get_char") + FAKE_OP("string_find_char") + FAKE_OP("string_slice") + FAKE_OP("string_to_int") + FAKE_OP("string_to_nat") + FAKE_OP("string_to_real") } else { /* some other identifier */ printf("Unknown id at line %d: %.*s\n", token.line, token.length, @@ -484,7 +884,6 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { st->count++; st->scopes[st->count].parent = st->scope_ref; st->scope_ref = (i32)st->count; - st->depth++; continue; } @@ -493,7 +892,6 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { i32 parent = st->scopes[current_scope].parent; if (parent < 0) parent = 0; st->scope_ref = parent; - st->depth--; continue; } @@ -506,32 +904,30 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { continue; } - if (token.type == TOKEN_KEYWORD_PLEX) { - /* ignore, already processed */ - /* FIXME: consume all tokens for this plex */ - continue; - } - - if (token.type == TOKEN_TYPE_I8 || - token.type == TOKEN_TYPE_I16 || - token.type == TOKEN_TYPE_INT || - token.type == TOKEN_TYPE_U8 || - token.type == TOKEN_TYPE_U16 || - token.type == TOKEN_TYPE_NAT || - token.type == TOKEN_TYPE_REAL || + if (token.type == TOKEN_TYPE_PTR || token.type == TOKEN_TYPE_I8 || + token.type == TOKEN_TYPE_I16 || token.type == TOKEN_TYPE_INT || + token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || + token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || token.type == TOKEN_TYPE_STR) { - /* ignore, already processed */ - next_token(); /* type */ - next_token(); /* var */ - next_token(); /* reg */ - next_token(); /* ; */ + if (st->depth > 0) { + /* ignore, local already processed */ + next_token(); /* type */ + next_token(); /* var */ + next_token(); /* reg */ + next_token(); /* ; */ + } else { + /* ignore, global already processed */ + next_token(); /* type */ + next_token(); /* var */ + next_token(); /* eq */ + next_token(); /* value */ + next_token(); /* ; */ + } continue; } - if (token.type == TOKEN_KEYWORD_LOOP || - token.type == TOKEN_KEYWORD_IF || - token.type == TOKEN_KEYWORD_ELSE || - token.type == TOKEN_KEYWORD_DO || + if (token.type == TOKEN_KEYWORD_LOOP || token.type == TOKEN_KEYWORD_IF || + token.type == TOKEN_KEYWORD_ELSE || token.type == TOKEN_KEYWORD_DO || token.type == TOKEN_KEYWORD_FOR) { /* ignore, already processed */ next_token(); /* id */ @@ -549,7 +945,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { continue; } - u32 reg = get_ref(st, next.start, next.length); + u32 reg = get_reg(next, st); emit_byte(vm, reg); vm->cp++; next_token_is(TOKEN_SEMICOLON); @@ -560,8 +956,1405 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { printf("-- %.*s --\n", token.length, token.start); #endif if (token.type == TOKEN_IDENTIFIER) { - if (false) { + /* check to see if it is an opcode first */ + if (strleq(token.start, "exit", token.length)) { + emit_op(vm, OP_EXIT); + vm->cp++; + + Token next = next_token(); + u32 ptr = get_ptr(next, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "call", token.length)) { + + emit_op(vm, OP_CALL); + vm->cp++; + + Token id = next_token_is(TOKEN_IDENTIFIER); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + u8 arg_count = 0; + u32 arg_pos = vm->cp++; + Token next = next_token_is(TOKEN_LPAREN); + next = next_token(); + while (next.type != TOKEN_RPAREN) { + u8 arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + arg_count++; + next = next_token(); + } + + vm->code[arg_pos] = arg_count; + +#ifdef DEBUG_PRINT + printf("^code[%d] = %d\n", arg_pos, arg_count); +#endif + + next = next_token(); + if (next.type == TOKEN_SEMICOLON) { + emit_byte(vm, 255); + vm->cp++; + } else { + next = next_token(); + u8 arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + } + + continue; + } else if (strleq(token.start, "syscall", token.length)) { + + emit_op(vm, OP_SYSCALL); + vm->cp++; + + Token next = next_token(); + + u32 syscall_id = 0; + const char *syscall_name = next.start; + if (strleq(syscall_name, "EXIT", next.length)) + syscall_id = SYSCALL_EXIT; + else if (strleq(syscall_name, "OPEN", next.length)) + syscall_id = SYSCALL_DEVICE_OPEN; + else if (strleq(syscall_name, "READ", next.length)) + syscall_id = SYSCALL_DEVICE_READ; + else if (strleq(syscall_name, "WRITE", next.length)) + syscall_id = SYSCALL_DEVICE_WRITE; + else if (strleq(syscall_name, "CLOSE", next.length)) + syscall_id = SYSCALL_DEVICE_CLOSE; + else if (strleq(syscall_name, "IOCTL", next.length)) + syscall_id = SYSCALL_DEVICE_IOCTL; + else if (strleq(syscall_name, "REFRESH", next.length)) + syscall_id = SYSCALL_DEVICE_REFRESH; + + emit_u32(vm, syscall_id); + vm->cp += 4; + + next = next_token(); + while (next.type != TOKEN_SEMICOLON && + next.type != TOKEN_ARROW_RIGHT) { + u8 arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next = next_token(); + } + + if (next.type == TOKEN_ARROW_RIGHT) { + next = next_token(); + u8 arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + } + + } else if (strleq(token.start, "load_immediate", token.length)) { + + emit_op(vm, OP_LOAD_IMM); + vm->cp++; + + Token value = next_token(); + switch (value.type) { + case TOKEN_KEYWORD_TRUE: { + emit_u32(vm, 1); + break; + } + case TOKEN_KEYWORD_FALSE: { + emit_u32(vm, 0); + break; + } + case TOKEN_LITERAL_INT: { + i32 out = atoi(value.start); + emit_u32(vm, out); + break; + } + case TOKEN_LITERAL_NAT: { + char *endptr; + u32 out = (u32)strtoul(value.start, &endptr, 10); + if (endptr == value.start || *endptr != '\0') { + fprintf(stderr, "Invalid 'real' number: '%.*s'\n", token.length, + token.start); + exit(1); + } + emit_u32(vm, out); + break; + } + case TOKEN_LITERAL_REAL: { + r32 out = float_to_real(atof(value.start)); + emit_u32(vm, out); + break; + } + default: { + fprintf(stderr, "Unknown immediate: '%.*s'\n", token.length, + token.start); + exit(1); + } + } + + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_address", token.length)) { + emit_op(vm, OP_LOAD_IMM); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "malloc", token.length)) { + emit_op(vm, OP_MALLOC); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "memset_8", token.length)) { + emit_op(vm, OP_MEMSET_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "memset_16", token.length)) { + emit_op(vm, OP_MEMSET_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "memset_32", token.length)) { + emit_op(vm, OP_MEMSET_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_offset_8", token.length)) { + emit_op(vm, OP_LOAD_OFF_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_offset_16", token.length)) { + emit_op(vm, OP_LOAD_OFF_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_offset_32", token.length)) { + emit_op(vm, OP_LOAD_OFF_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_indirect_8", token.length)) { + emit_op(vm, OP_LOAD_IND_8); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_indirect_16", token.length)) { + emit_op(vm, OP_LOAD_IND_16); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_indirect_32", token.length)) { + emit_op(vm, OP_LOAD_IND_32); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_absolute_8", token.length)) { + emit_op(vm, OP_LOAD_ABS_8); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_absolute_16", token.length)) { + emit_op(vm, OP_LOAD_ABS_16); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_absolute_32", token.length)) { + emit_op(vm, OP_LOAD_ABS_32); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_absolute_8", token.length)) { + emit_op(vm, OP_STORE_ABS_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_absolute_16", token.length)) { + emit_op(vm, OP_STORE_ABS_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_absolute_32", token.length)) { + emit_op(vm, OP_STORE_ABS_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_indirect_8", token.length)) { + emit_op(vm, OP_STORE_IND_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_indirect_16", token.length)) { + emit_op(vm, OP_STORE_IND_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_indirect_32", token.length)) { + emit_op(vm, OP_STORE_IND_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_offset_8", token.length)) { + emit_op(vm, OP_STORE_OFF_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_offset_16", token.length)) { + emit_op(vm, OP_STORE_OFF_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_offset_32", token.length)) { + emit_op(vm, OP_STORE_OFF_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "register_move", token.length)) { + emit_op(vm, OP_REG_MOV); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "add_int", token.length)) { + emit_op(vm, OP_ADD_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "sub_int", token.length)) { + emit_op(vm, OP_SUB_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "mul_int", token.length)) { + emit_op(vm, OP_MUL_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "div_int", token.length)) { + emit_op(vm, OP_DIV_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "abs_int", token.length)) { + emit_op(vm, OP_ABS_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "neg_int", token.length)) { + emit_op(vm, OP_NEG_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "add_nat", token.length)) { + emit_op(vm, OP_ADD_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "sub_nat", token.length)) { + emit_op(vm, OP_SUB_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "mul_nat", token.length)) { + emit_op(vm, OP_MUL_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "div_nat", token.length)) { + emit_op(vm, OP_DIV_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "abs_nat", token.length)) { + emit_op(vm, OP_ABS_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "neg_nat", token.length)) { + emit_op(vm, OP_NEG_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "add_real", token.length)) { + emit_op(vm, OP_ADD_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + ; + } else if (strleq(token.start, "sub_real", token.length)) { + emit_op(vm, OP_SUB_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "mul_real", token.length)) { + emit_op(vm, OP_MUL_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "div_real", token.length)) { + emit_op(vm, OP_DIV_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "abs_real", token.length)) { + emit_op(vm, OP_ABS_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "neg_real", token.length)) { + emit_op(vm, OP_NEG_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "int_to_real", token.length)) { + emit_op(vm, OP_INT_TO_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "nat_to_real", token.length)) { + emit_op(vm, OP_NAT_TO_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "real_to_int", token.length)) { + emit_op(vm, OP_REAL_TO_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "real_to_nat", token.length)) { + emit_op(vm, OP_REAL_TO_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_shift_left", token.length)) { + emit_op(vm, OP_BIT_SHIFT_LEFT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_shift_right", token.length)) { + emit_op(vm, OP_BIT_SHIFT_RIGHT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_shift_r_ext", token.length)) { + emit_op(vm, OP_BIT_SHIFT_R_EXT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_and", token.length)) { + emit_op(vm, OP_BAND); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_or", token.length)) { + emit_op(vm, OP_BOR); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_xor", token.length)) { + emit_op(vm, OP_BXOR); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump", token.length)) { + emit_op(vm, OP_JMP); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_if_flag", token.length)) { + emit_op(vm, OP_JMPF); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_eq_int", token.length)) { + emit_op(vm, OP_JEQ_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_neq_int", token.length)) { + emit_op(vm, OP_JNEQ_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_gt_int", token.length)) { + emit_op(vm, OP_JGT_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_lt_int", token.length)) { + emit_op(vm, OP_JLT_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_le_int", token.length)) { + emit_op(vm, OP_JLE_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_ge_int", token.length)) { + emit_op(vm, OP_JGE_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_eq_nat", token.length)) { + emit_op(vm, OP_JEQ_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_neq_nat", token.length)) { + emit_op(vm, OP_JNEQ_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_gt_nat", token.length)) { + emit_op(vm, OP_JGT_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_lt_nat", token.length)) { + emit_op(vm, OP_JLT_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_le_nat", token.length)) { + emit_op(vm, OP_JLE_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_ge_nat", token.length)) { + emit_op(vm, OP_JGE_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_eq_real", token.length)) { + emit_op(vm, OP_JEQ_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_neq_real", token.length)) { + emit_op(vm, OP_JNEQ_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_ge_real", token.length)) { + emit_op(vm, OP_JGE_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_gt_real", token.length)) { + emit_op(vm, OP_JGT_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_lt_real", token.length)) { + emit_op(vm, OP_JLT_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_le_real", token.length)) { + emit_op(vm, OP_JLE_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "string_length", token.length)) { + emit_op(vm, OP_STRLEN); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "int_to_string", token.length)) { + emit_op(vm, OP_INT_TO_STRING); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "nat_to_string", token.length)) { + emit_op(vm, OP_NAT_TO_STRING); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "real_to_string", token.length)) { + emit_op(vm, OP_REAL_TO_STRING); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + ; + } else if (strleq(token.start, "string_eq", token.length)) { + } else if (strleq(token.start, "string_concat", token.length)) { + } else if (strleq(token.start, "string_get_char", token.length)) { + } else if (strleq(token.start, "string_find_char", token.length)) { + } else if (strleq(token.start, "string_slice", token.length)) { + } else if (strleq(token.start, "string_to_int", token.length)) { + } else if (strleq(token.start, "string_to_nat", token.length)) { + } else if (strleq(token.start, "string_to_real", token.length)) { } else { /* some other identifier */ printf("Unknown id at line %d: %.*s\n", token.line, token.length, diff --git a/src/tools/compiler/parser.c b/src/tools/compiler/parser.c index 3bbdf86..01f83f4 100644 --- a/src/tools/compiler/parser.c +++ b/src/tools/compiler/parser.c @@ -119,10 +119,10 @@ static TokenType checkKeyword(int start, int length, const char *rest, } static TokenType identifierType() { - switch (lexer.start[0]) { + switch (parser.start[0]) { case 'a': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'n': return checkKeyword(2, 1, "d", TOKEN_OPERATOR_AND); case 's': @@ -131,8 +131,8 @@ static TokenType identifierType() { } break; case 'c': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'l': return checkKeyword(2, 3, "ose", TOKEN_KEYWORD_CLOSE); case 'o': @@ -143,8 +143,8 @@ static TokenType identifierType() { case 'e': return checkKeyword(1, 3, "lse", TOKEN_KEYWORD_ELSE); case 'f': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'a': return checkKeyword(2, 3, "lse", TOKEN_KEYWORD_FALSE); case 'o': @@ -156,8 +156,8 @@ static TokenType identifierType() { } break; case 'i': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'f': return checkKeyword(2, 0, "", TOKEN_KEYWORD_IF); case 's': @@ -169,8 +169,8 @@ static TokenType identifierType() { case '3': return checkKeyword(2, 1, "2", TOKEN_TYPE_INT); case 'n': - if (lexer.current - lexer.start > 2) { - switch (lexer.start[2]) { + if (parser.current - parser.start > 2) { + switch (parser.start[2]) { case 'i': return checkKeyword(3, 2, "t", TOKEN_KEYWORD_INIT); case 't': @@ -182,8 +182,8 @@ static TokenType identifierType() { } break; case 'n': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'a': return checkKeyword(2, 1, "t", TOKEN_TYPE_NAT); case 'i': @@ -192,8 +192,8 @@ static TokenType identifierType() { } break; case 'o': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'p': return checkKeyword(2, 2, "en", TOKEN_KEYWORD_OPEN); case 'r': @@ -202,19 +202,21 @@ static TokenType identifierType() { } break; case 'p': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { + case 't': + return checkKeyword(2, 1, "r", TOKEN_TYPE_PTR); case 'l': return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX); } } break; case 'r': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'e': - if (lexer.current - lexer.start > 2) { - switch (lexer.start[2]) { + if (parser.current - parser.start > 2) { + switch (parser.start[2]) { case 'a': return checkKeyword(3, 1, "d", TOKEN_KEYWORD_READ); case 't': @@ -226,11 +228,11 @@ static TokenType identifierType() { } break; case 's': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 't': - if (lexer.current - lexer.start > 2) { - switch (lexer.start[2]) { + if (parser.current - parser.start > 2) { + switch (parser.start[2]) { case 'r': return checkKeyword(2, 0, "", TOKEN_TYPE_STR); case 'a': @@ -241,8 +243,8 @@ static TokenType identifierType() { } break; case 't': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'h': return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS); case 'r': @@ -251,8 +253,8 @@ static TokenType identifierType() { } break; case 'u': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 's': return checkKeyword(2, 1, "e", TOKEN_KEYWORD_USE); case '8': @@ -265,8 +267,8 @@ static TokenType identifierType() { } break; case 'w': - if (lexer.current - lexer.start > 1) { - switch (lexer.start[1]) { + if (parser.current - parser.start > 1) { + switch (parser.start[1]) { case 'h': return checkKeyword(2, 3, "ile", TOKEN_KEYWORD_WHILE); case 'r': @@ -401,6 +403,8 @@ const char *token_type_to_string(TokenType type) { return "TYPE_REAL"; case TOKEN_TYPE_STR: return "TYPE_STR"; + case TOKEN_TYPE_PTR: + return "TYPE_PTR"; case TOKEN_KEYWORD_PLEX: return "KEYWORD_PLEX"; case TOKEN_KEYWORD_FN: @@ -433,8 +437,8 @@ const char *token_type_to_string(TokenType type) { return "TOKEN_KEYWORD_READ"; case TOKEN_KEYWORD_WRITE: return "TOKEN_KEYWORD_WRITE"; - case TOKEN_KEYWORD_REFRESH: - return "TOKEN_KEYWORD_REFRESH"; + case TOKEN_KEYWORD_STAT: + return "TOKEN_KEYWORD_STAT"; case TOKEN_KEYWORD_CLOSE: return "TOKEN_KEYWORD_CLOSE"; case TOKEN_KEYWORD_NIL: diff --git a/src/tools/compiler/parser.h b/src/tools/compiler/parser.h index 72713ad..f8282e4 100644 --- a/src/tools/compiler/parser.h +++ b/src/tools/compiler/parser.h @@ -18,6 +18,7 @@ typedef enum { TOKEN_TYPE_STR, TOKEN_TYPE_BOOL, TOKEN_TYPE_VOID, + TOKEN_TYPE_PTR, TOKEN_KEYWORD_PLEX, TOKEN_KEYWORD_FN, TOKEN_KEYWORD_CONST, @@ -34,7 +35,7 @@ typedef enum { TOKEN_KEYWORD_OPEN, TOKEN_KEYWORD_READ, TOKEN_KEYWORD_WRITE, - TOKEN_KEYWORD_REFRESH, + TOKEN_KEYWORD_STAT, TOKEN_KEYWORD_CLOSE, TOKEN_KEYWORD_LOOP, TOKEN_KEYWORD_DO, diff --git a/test/add.uir.ul b/test/add.uir.ul index 4e33824..75f4b79 100644 --- a/test/add.uir.ul +++ b/test/add.uir.ul @@ -1,47 +1,38 @@ -/** - * Constants - */ -str term_namespace = "/dev/term/0"; -str nl = "\n"; -int x = 0; +str terminal_namespace = "/dev/term/0"; +str new_line = "\n"; +int x = 1; int y = 1; -plex Terminal { - nat handle; +function main () { + load_absolute_32 x -> $0; + load_absolute_32 y -> $1; + call add ($0 $1) -> $2; + int_to_string $2 -> $3; + call pln ($3); + exit 0; } -/** - * Main function - */ -function main() { - int tmp0 = x; - int tmp1 = y; - int tmp2 = add(tmp0, tmp1); - str tmp3 = tmp2 as str; - pln(tmp3); +function add (int a, int b) { + int result; + add_int a b -> result; + return result; } -/** - * Add two numbers together - */ -function add(int a, int b) int { - int tmp0 = a + b; - return tmp0; -} - -/** - * Print with a newline - */ -function pln(str message) { - str term_ns = term_namespace; - int mode = 0; - - Terminal term = open(term_ns, mode); - - int msg_len = message.length; - write(term, message, msg_len); - - str nl_local = nl; - int nl_len = nl.length; - write(term, nl_local, nl_len); +function pln (str message) { + ptr term; + int msg_length; + str nl; + int nl_length; + int mode; + str term_ns; + + load_immediate 0 -> mode; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode term; + string_length message -> msg_length; + syscall WRITE term message msg_length; + load_address new_line -> nl; + string_length nl -> nl_length; + syscall WRITE term nl nl_length; + return; } diff --git a/test/fib.uir.ul b/test/fib.uir.ul index 4cb6d6e..6843bde 100644 --- a/test/fib.uir.ul +++ b/test/fib.uir.ul @@ -1,60 +1,51 @@ -/** - * Constants - */ -str term_namespace = "/dev/term/0"; -str nl = "\n"; +str terminal_namespace = "/dev/term/0"; +str new_line = "\n"; -plex Terminal { - nat handle; +function main () { + int str_n; + + load_immediate 35 -> $0; + call fib ($0) -> $0; + int_to_string $0 -> str_n; + call pln (str_n); + exit 0; } -/** - * Main function - */ -function main() { - int fib = 35; - int ans = fib(35); - str ans_s = ans as str; - pln(ans_s); +function fib (int n) { + load_immediate 2 -> $1; + + jump_lt_int base_case n $1; + + load_immediate 2 -> $3; + sub_int n $3 -> $4; + call fib ($4) -> $5; + + load_immediate 1 -> $3; + sub_int n $3 -> $4; + call fib ($4) -> $6; + + add_int $6 $5 -> $7; + return $7; + + else base_case; + return n; } -/** - * Recursively calculate fibonacci - */ -function fib(int n) int { - int base_check = 2; +function pln (str message) { + ptr term; + int msg_length; + str nl; + int nl_length; + int mode; + str term_ns; - jump_lt_int base_case n base_check; - jump end1; - do base_case; - return n; - else base_case_end; - - int tmp_c2 = 2; - int tmp_c2_n = n - tmp_c2; - int ans_c2 = fib(tmp_c2_n); - - int tmp_c1 = 1; - int tmp_c1_n = tmp_c1 - n; - int ans_c1 = fib(tmp_c1_n); - - int ans = tmp_c1_n + tmp_c2_n; - return ans; -} - -/** - * Print with a newline - */ -function pln(str message) { - str term_ns = term_namespace; - int mode = 0; - - Terminal term = open(term_ns, mode); - - int msg_len = message.length; - write(term, message, msg_len); - - str nl_local = nl; - int nl_len = nl.length; - write(term, nl_local, nl_len); + load_immediate 0 -> mode; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode term; + string_length message -> msg_length; + syscall WRITE term message msg_length; + load_address new_line -> nl; + string_length nl -> nl_length; + syscall WRITE term nl nl_length; + return; } diff --git a/test/hello.uir.ul b/test/hello.uir.ul index e54ea7e..366ec98 100644 --- a/test/hello.uir.ul +++ b/test/hello.uir.ul @@ -1,32 +1,30 @@ -str term_namespace = "/dev/term/0"; +str terminal_namespace = "/dev/term/0"; +str new_line = "\n"; str hello = "nuqneH 'u'?"; -str nl = "\n"; -plex Terminal { - nat handle; +function main () { + str msg; + + load_address hello -> msg; + call pln (msg); + exit 0; } -/** - * Main function - */ -function main() { - str msg = hello; - pln(msg); -} - -/** - * Print with a newline - */ -function pln(str message) { - str term_ns = term_namespace; - int mode = 0; - - Terminal term = open(term_ns, mode); - - int msg_len = message.length; - write(term, message, msg_len); - - str nl_local = nl; - int nl_len = nl.length; - write(term, nl_local, nl_len); +function pln (str message) { + ptr term; + int msg_length; + str nl; + int nl_length; + int mode; + str term_ns; + + load_immediate 0 -> mode; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode term; + string_length message -> msg_length; + syscall WRITE term message msg_length; + load_address new_line -> nl; + string_length nl -> nl_length; + syscall WRITE term nl nl_length; + return; } diff --git a/test/loop.uir.ul b/test/loop.uir.ul index 8a37d99..214d0cb 100644 --- a/test/loop.uir.ul +++ b/test/loop.uir.ul @@ -1,65 +1,63 @@ -str term_namespace = "/dev/term/0"; +str terminal_namespace = "/dev/term/0"; str prompt = "Enter a string:"; -str nl = "\n"; +str new_line = "\n"; +function main () { + real a; + int i; + int mode $11; + str term $10; -plex Terminal { - nat handle; + // do (i = 5000; i >= 0, i = i - 1) + load_immediate 5.0 -> a; + load_immediate 5000 -> i; + load_immediate 0 -> $2; + load_immediate -1 -> $3; + load_immediate 5.0 -> $5; + loop loop_body { + add_real a $5 -> a; + add_int i $3 -> i; + jump_ge_int loop_body i $2; + } + + load_address terminal_namespace -> term; + load_immediate 0 -> mode; + syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0); + + nat b $1; + real_to_nat a -> b; + load_address prompt -> $7; + string_length $7 -> $8; + syscall WRITE term $7 $8; // print prompt + + str user_string $9; + load_immediate 32 -> $8; + malloc $8 -> user_string; + syscall READ term user_string $8; // read in max 32 byte string + + call pln (user_string); + nat_to_string b -> $4; + call pln ($4); + real_to_string a -> $3; + call pln ($3); + exit 0; } -/** - * Main function - */ -function main() { - str term_ns = term_namespace; - int mode = 0; +function pln (str message) { + ptr term; + int msg_length; + str nl; + int nl_length; + int mode; + str term_ns; - Terminal term = open(term_ns, mode); - - real a = 5.0; - - // do (int i = 5000; i >= 0, i = i - 1) - int i = 5000; - int tmp0 = 0; - int tmp1 = 1; - int tmp2 = 5.0; - loop loop_body { - a = a + tmp2; - i = i - tmp1; - jump_ge_int loop_body i tmp0; - } - - nat b = a as nat; - str local_prompt = prompt; - pln(local_prompt); - - nat size = 32; - str user_string = malloc(size); - read(term, user_string, size); - - str a_str = a as str; - pln(a_str); - - str b_str = b as str; - pln(b_str); - - pln(user_string); + load_immediate 0 -> mode; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode term; + string_length message -> msg_length; + syscall WRITE term message msg_length; + load_address new_line -> nl; + string_length nl -> nl_length; + syscall WRITE term nl nl_length; + return; } - -/** - * Print with a newline - */ -function pln(str message) { - str term_ns = term_namespace; - int mode = 0; - - Terminal term = open(term_ns, mode); - - int msg_len = message.length; - write(term, message, msg_len); - - str nl_local = nl; - int nl_len = nl.length; - write(term, nl_local, nl_len); -} - diff --git a/test/malloc.uir.ul b/test/malloc.uir.ul index 6c81ea3..68ca279 100644 --- a/test/malloc.uir.ul +++ b/test/malloc.uir.ul @@ -1,26 +1,43 @@ -/** - * Constants - */ -const str nl = "\n"; +str terminal_namespace = "/dev/term/0"; +str prompt = "Enter a string:"; +str new_line = "\n"; -plex Terminal { - nat handle; +function main () { + int mode; + str term; + + load_address terminal_namespace -> term; + load_immediate 0 -> mode; + syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0); + + load_address prompt -> $7; + string_length $7 -> $8; + syscall WRITE term $7 $8; // print prompt + + str user_string; + load_immediate 32 -> $8; + malloc $8 -> user_string; + syscall READ term user_string $8; // read in max 32 byte string + + call pln (user_string); + exit 0; } -/** - * Main function - */ -function main() { - Terminal term = open("/dev/term/0", 0); - pln(term, "Enter a string: "); - pln(term, term.read(32)); - return 0; -} +function pln (str message) { + ptr term; + int msg_length; + str nl; + int nl_length; + int mode; + str term_ns; -/** - * Print with a newline - */ -function pln(Terminal term, str message) { - write(term, message, message.length); - write(term, nl, nl.length); + load_immediate 0 -> mode; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode term; + string_length message -> msg_length; + syscall WRITE term message msg_length; + load_address new_line -> nl; + string_length nl -> nl_length; + syscall WRITE term nl nl_length; + return; } diff --git a/test/paint.uir.ul b/test/paint.uir.ul index 55a017d..7c5045b 100644 --- a/test/paint.uir.ul +++ b/test/paint.uir.ul @@ -34,188 +34,195 @@ byte DARK_ORANGE = 208; byte GOLD = 244; byte SELECTED_COLOR = 255; -plex Screen { - nat handle; - nat width; - nat height; - byte[] buffer; -} - -plex Mouse { - nat handle; - nat x; - nat y; - bool left; - bool right; - bool middle; - bool btn4; -} - function main () { - str screen_name = screen_namespace; - int mode = 0; - Screen screen = open(screen_name, mode); + // Open screen + ptr screen $0; + str screen_name $18; + int mode $11; + nat screen_buffer $21; - nat width = screen.width; - nat size = screen.size; - nat screen_offset = 16; - nat screen_buffer = screen_buffer + screen_offset; + // use load immediate because it a pointer to a string, not a value + load_address screen_namespace -> screen_name; + load_immediate 0 -> mode; + syscall OPEN screen_name mode screen; // Screen screen = open("/dev/screen/0", 0); + + nat width $20; + nat size $22; + load_offset_32 screen 8 -> width; // load width + load_offset_32 screen 12 -> size; // load size + load_immediate 16 -> $1; // offset for screen buffer + add_nat screen $1 -> screen_buffer; // open mouse - str mouse_name = mouse_namespace; - Mouse mouse = open(mouse_name, mode); + ptr mouse $15; + str mouse_name $16; + load_address mouse_namespace -> mouse_name; + syscall OPEN mouse_name mode mouse; // Mouse mouse = open("/dev/mouse/0", 0); - byte color = BLACK; - nat x_pos = 1; - nat y_pos = 1; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + byte color $1; + nat x_pos $12; + nat y_pos $13; - color = WHITE; - x_pos = 21; - y_pos = 1; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 BLACK -> color; + load_immediate 1 -> x_pos; + load_immediate 1 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = CHARCOAL; - x_pos = 1; - y_pos = 21; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 WHITE -> color; + load_immediate 21 -> x_pos; + load_immediate 1 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = DARK_GRAY; - x_pos = 21; - y_pos = 21; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 CHARCOAL -> color; + load_immediate 1 -> x_pos; + load_immediate 21 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = RED; - x_pos = 1; - y_pos = 41; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 DARK_GRAY -> color; + load_immediate 21 -> x_pos; + load_immediate 21 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = ORANGE; - x_pos = 21; - y_pos = 41; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 RED -> color; + load_immediate 1 -> x_pos; + load_immediate 41 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = YELLOW; - x_pos = 1; - y_pos = 61; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 ORANGE -> color; + load_immediate 21 -> x_pos; + load_immediate 41 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = GREEN; - x_pos = 21; - y_pos = 61; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 YELLOW -> color; + load_immediate 1 -> x_pos; + load_immediate 61 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = BLUE; - x_pos = 1; - y_pos = 81; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 GREEN -> color; + load_immediate 21 -> x_pos; + load_immediate 61 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); - color = PURPLE; - x_pos = 21; - y_pos = 81; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); + load_absolute_8 BLUE -> color; + load_immediate 1 -> x_pos; + load_immediate 81 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + + load_absolute_8 PURPLE -> color; + load_immediate 21 -> x_pos; + load_immediate 81 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); // screen.draw - write(screen, screen_buffer, size); + syscall WRITE screen screen_buffer size; - nat zero = 0; + nat m_zero $11; - loop draw { + loop draw_loop { // load mouse click data - refresh(mouse); + syscall REFRESH mouse; - byte left_down = mouse.down; + byte left_down $9; + load_offset_8 mouse 16 -> left_down; // load btn1 pressed - jump_eq_nat draw left_down zero; // if (!btn1.left) continue; + jump_eq_nat draw_loop left_down m_zero; // if (!btn1.left) continue; - nat mouse_x = mouse.x; - nat mouse_y = mouse.y; + nat mouse_x $7; + nat mouse_y $8; + load_offset_32 mouse 8 -> mouse_x; // load x + load_offset_32 mouse 12 -> mouse_y; // load y - nat box_size = 20; + nat box_size $14; + load_immediate 20 -> box_size; // first row - color = BLACK; - x_pos = 1; - y_pos = 1; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 BLACK -> color; + load_immediate 1 -> x_pos; + load_immediate 1 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = WHITE; - x_pos = 21; - y_pos = 1; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 WHITE -> color; + load_immediate 21 -> x_pos; + load_immediate 1 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = CHARCOAL; - x_pos = 1; - y_pos = 21; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 CHARCOAL -> color; + load_immediate 1 -> x_pos; + load_immediate 21 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - DARK_GRAY -> color; - x_pos = 21; - y_pos = 21; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 DARK_GRAY -> color; + load_immediate 21 -> x_pos; + load_immediate 21 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = RED; - x_pos = 1; - y_pos = 41; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 RED -> color; + load_immediate 1 -> x_pos; + load_immediate 41 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = ORANGE; - x_pos = 21; - y_pos = 41; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 ORANGE -> color; + load_immediate 21 -> x_pos; + load_immediate 41 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = YELLOW; - x_pos = 1; - y_pos = 61; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 YELLOW -> color; + load_immediate 1 -> x_pos; + load_immediate 61 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = GREEN; - x_pos = 21; - y_pos = 61; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 GREEN -> color; + load_immediate 21 -> x_pos; + load_immediate 61 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = BLUE; - x_pos = 1; - y_pos = 81; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 BLUE -> color; + load_immediate 1 -> x_pos; + load_immediate 81 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - color = PURPLE; - x_pos = 21; - y_pos = 81; - draw_outlined_swatch(screen_buffer, color, x_pos, y_pos, width); - set_color(mouse_x, mouse_y, x_pos, y_pos, color, box_size); + load_absolute_8 PURPLE -> color; + load_immediate 21 -> x_pos; + load_immediate 81 -> y_pos; + call draw_outlined_swatch (screen_buffer color x_pos y_pos width); + call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size); - write(screen, screen_buffer, size); + syscall WRITE screen screen_buffer size; - byte selected_color = SELECTED_COLOR; + byte selected_color $25; + load_absolute_8 SELECTED_COLOR -> selected_color; - nat brush_size = 5; + nat brush_size $19; + load_immediate 5 -> brush_size; - draw_box(screen_buffer, width, selected_color, mouse_x, mouse_y, brush_size, brush_size); + call draw_box (screen_buffer width selected_color mouse_x mouse_y brush_size brush_size); - jump draw; + jump draw_loop; } // Flush and exit exit 0; } -function set_color (int click_x, int click_y, int box_x, int box_y, byte check_color, int size) { +function set_color_if_clicked (int click_x $0, int click_y $1, + int box_x $2, int box_y $3, byte check_color $4, int bsize $5) { // Compute right - int right_edge = box_x + size; + int right_edge $6; + add_int box_x bsize -> right_edge; - // Compute bottom = box_y + size - int bottom_edge = box_y + size; + // Compute bottom = box_y + bsize + int bottom_edge $7; + add_int box_y bsize -> bottom_edge; // Bounds check: x in [box_x, right] and y in [box_y, bottom] jump_lt_int fail click_x box_x; @@ -223,56 +230,73 @@ function set_color (int click_x, int click_y, int box_x, int box_y, byte check_c jump_lt_int fail click_y box_y; jump_gt_int fail click_y bottom_edge; - SELECTED_COLOR = check_color; + store_absolute_8 check_color -> SELECTED_COLOR; else fail return; } -function draw_outlined_swatch(nat base, byte swatch_color, int x, int y, int width) { +function draw_outlined_swatch(nat base, + byte swatch_color, int x, int y, int width) { - nat background_color = GRAY; - byte selected_color = SELECTED_COLOR; + // Constants + nat background_color; + load_absolute_8 GRAY -> background_color; + + byte selected_color; + load_absolute_8 SELECTED_COLOR -> selected_color; jump_eq_int set_selected swatch_color selected_color; jump end_set_selected; do set_selected - background_color = DARK_GRAY; + load_absolute_8 DARK_GRAY -> background_color; else end_set_selected - nat outline_size = 20; - nat fill_size = 17; + nat outline_size; + load_immediate 20 -> outline_size; - draw_box(base, width, background_color, x, y, outline_size, outline_size); + nat fill_size; + load_immediate 17 -> fill_size; - nat offset = 2; - int xO = x + offset; // x + 2 - int yO = y + offset; // y + 2 + nat offset; + load_immediate 2 -> offset; - draw_box(base, width, swatch_color, xO, yO, fill_size, fill_size); + call draw_box (base width background_color x y outline_size outline_size); + + int x_off; + int y_off; + add_int x offset -> x_off; // x + 2 + add_int y offset -> y_off; // y + 2 + + call draw_box (base width swatch_color x_off y_off fill_size fill_size); return; } -function draw_box (nat base, nat screen_width, byte box_color, - nat x, nat y, nat width, nat height) { - - nat fat_ptr_size = 4; +function draw_box (nat db_base, nat screen_width, + byte box_color, nat x_start, nat y_start, + nat db_width, nat height) { // Compute start address: base + y*640 + x - nat offset = y * screen_width; - offset = offset + x; - offset = offset + base; - offset = offset + fat_ptr_size; // need to add offset for fat pointer size + nat offset; + mul_int y_start screen_width -> offset; + add_int offset x_start -> offset; + add_nat offset db_base -> offset; + nat fat_ptr_size; + load_immediate 4 -> fat_ptr_size; + add_nat offset fat_ptr_size -> offset; // need to add offset for fat pointer size - int i = 1; - int zero = 0; + int i; + load_immediate 1 -> i; + + int zero; + load_immediate 0 -> zero; loop draw_box_outer { - memset(offset, width, box_color); // draw row - offset = offset + screen_width; // next row += 640 - height = height - i; // decrement row count + memset_8 box_color db_width -> offset; // draw row + add_int offset screen_width -> offset; // next row += 640 + sub_int height i -> height; // decrement row count jump_gt_int draw_box_outer height zero; } return; -} +} \ No newline at end of file