1
0
Fork 0

Update assembler to add scopes

This commit is contained in:
zongor 2025-12-20 00:42:28 -08:00
parent 0fd2656704
commit 4114812146
16 changed files with 236 additions and 318 deletions

View File

@ -89,7 +89,7 @@ void mainloop() {
}
int cycles_this_frame = 0;
int max_cycles_per_frame = 2000;
int max_cycles_per_frame = 1000;
while (cycles_this_frame < max_cycles_per_frame) {
if (!step_vm(&vm)) {
emscripten_cancel_main_loop();
@ -181,4 +181,4 @@ int main(int argc, char **argv) {
emscripten_set_main_loop(mainloop, 0, 1);
return 0;
}
}

View File

@ -130,24 +130,29 @@ bool compileAndSave(const char *source_file, const char *output_file, VM *vm) {
}
#ifdef STATIC
#define SYMBOLS_COUNT 2048
Symbol symbols[SYMBOLS_COUNT];
#define SCOPES_COUNT 2048
SymbolTable scopes[SCOPES_COUNT];
#endif
void symbol_table_init(SymbolTable *t) {
void symbol_table_init(ScopeTable *t) {
#ifdef STATIC
memset(symbols, 0, SYMBOLS_COUNT*sizeof(Symbol));
t->symbols = symbols;
memset(scopes, 0, SCOPES_COUNT*sizeof(SymbolTable));
t->scopes = scopes;
t->count = 0;
t->capacity = SYMBOLS_COUNT;
t->capacity = SCOPES_COUNT;
#else
t->symbols = calloc(16, sizeof(Symbol));
t->scopes = calloc(16, sizeof(SymbolTable));
t->count = 0;
t->capacity = 16;
#endif
// Make sure that all the parents are the 'global' namespace.
for (u32 i = 0; i < t->capacity; i++) {
t->scopes[i].parent = -1;
}
}
bool resize_or_check_size(SymbolTable *table) {
bool table_realloc(ScopeTable *table) {
#ifdef STATIC
if (table->count >= table->capacity) {
return false;
@ -155,7 +160,12 @@ bool resize_or_check_size(SymbolTable *table) {
#else
if (table->count >= table->capacity) {
table->capacity *= 2;
table->symbols = realloc(table->symbols, table->capacity * sizeof(Symbol));
table->scopes = realloc(table->scopes, table->capacity * sizeof(SymbolTable));
// Make sure that all the parents are the 'global' namespace.
for (u32 i = table->count; i < table->capacity; i++) {
table->scopes[i].parent = -1;
}
}
#endif
return true;
@ -183,11 +193,11 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) {
source[read] = '\0';
fclose(f);
SymbolTable table = {0};
ScopeTable table = {0};
symbol_table_init(&table);
assemble(vm, &table, source);
#ifndef STATIC
free(table.symbols);
free(table.scopes);
#endif
if (output_file) {

View File

@ -162,35 +162,46 @@ void emit_u32(VM *vm, u32 value) {
write_u32(vm, code, vm->cp, value);
}
Symbol *symbol_table_lookup(SymbolTable *table, const char *name, u32 length) {
for (u32 i = 0; i < table->count; i++) {
if (table->symbols[i].name_length == length) {
if (strleq(table->symbols[i].name, name, length)) {
return &table->symbols[i];
Symbol *symbol_table_lookup(ScopeTable *table, const char *name, u32 length,
i32 scope_ref) {
SymbolTable st = table->scopes[scope_ref];
for (u32 i = 0; i < st.count; i++) {
if (st.symbols[i].name_length == length) {
if (strleq(st.symbols[i].name, name, length)) {
return &table->scopes[scope_ref].symbols[i];
}
}
}
return nil;
if (st.parent < 0)
return nil;
return symbol_table_lookup(table, name, length, st.parent);
}
u32 symbol_table_add(SymbolTable *table, Symbol s) {
Symbol *sym = symbol_table_lookup(table, s.name, s.name_length);
u8 symbol_table_add(ScopeTable *table, Symbol s) {
Symbol *sym =
symbol_table_lookup(table, s.name, s.name_length, table->scope_ref);
if (sym != nil) {
fprintf(stderr,
"Error: Symbol '%.*s' already defined, the assembler is not smart "
"enough to do scope properly so please pick a different variable "
"name (hard I know)\n",
"Error: Symbol '%.*s' already defined, in this scope"
" please pick a different variable name or create a new scope.\n",
s.name_length, s.name);
exit(1);
}
if (!resize_or_check_size(table)) {
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");
exit(1);
}
if (!table_realloc(table)) {
fprintf(stderr,
"Error: Symbol table is out of memory! This is likely because you "
"built the assembler in static mode, increase the static size."
"if you built using malloc, that means your computer is out of "
"memory. Close a few tabs in your web browser and try again."
"Count was %d, while capacity was %d\n",
" built the assembler in static mode, increase the static size."
" if you built using malloc, that means your computer is out of"
" memory. Close a few tabs in your web browser and try again."
" Count was %d, while capacity was %d\n",
table->count, table->capacity);
exit(1);
}
@ -203,15 +214,14 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) {
printf("code[%d] = %s\n", s.ref, s.name);
}
#endif
table->symbols[table->count] = s;
u32 index = table->count;
table->count++;
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 index;
}
u32 get_ref(SymbolTable *st, const char *name, u32 length) {
Symbol *sym = symbol_table_lookup(st, name, length);
u32 get_ref(ScopeTable *st, const char *name, u32 length) {
Symbol *sym = symbol_table_lookup(st, name, length, st->scope_ref);
if (!sym) {
fprintf(stderr, "Error: Assembler has no idea what Symbol '%.*s' means.\n",
length, name);
@ -221,7 +231,7 @@ u32 get_ref(SymbolTable *st, const char *name, u32 length) {
return sym->ref;
}
u32 get_ptr(Token token, SymbolTable *st) {
u32 get_ptr(Token token, ScopeTable *st) {
if (token.type == TOKEN_IDENTIFIER) {
return get_ref(st, token.start, token.length);
}
@ -246,7 +256,7 @@ u32 get_ptr(Token token, SymbolTable *st) {
exit(1);
}
u32 get_reg(Token token, SymbolTable *st) {
u32 get_reg(Token token, ScopeTable *st) {
if (token.type == TOKEN_IDENTIFIER) {
return get_ref(st, token.start, token.length);
}
@ -303,7 +313,7 @@ Token next_token_is(TokenType type) {
/**
* Global .
*/
bool define_global(VM *vm, SymbolTable *st) {
bool define_global(VM *vm, ScopeTable *st) {
Symbol s;
Token token_type = next_token();
@ -472,7 +482,7 @@ bool define_global(VM *vm, SymbolTable *st) {
/**
* Var .
*/
void define_var(SymbolTable *st, Token regType) {
void define_var(ScopeTable *st, Token regType) {
Symbol s;
s.scope = VAR;
switch (regType.type) {
@ -553,7 +563,7 @@ void define_var(SymbolTable *st, Token regType) {
/**
* function .
*/
void define_function(VM *vm, SymbolTable *st) {
void define_function(VM *vm, ScopeTable *st) {
Symbol s;
s.scope = LOCAL;
s.type = FUNCTION;
@ -570,6 +580,12 @@ void define_function(VM *vm, SymbolTable *st) {
next_token_is(TOKEN_LPAREN);
i32 temp = st->scope_ref;
st->count++;
st->scopes[st->count].parent = st->scope_ref;
st->scope_ref = (i32)st->count;
Token next = next_token();
while (next.type != TOKEN_RPAREN) {
define_var(st, next);
@ -585,13 +601,17 @@ void define_function(VM *vm, SymbolTable *st) {
}
}
s.ref = vm->cp;
next = next_token_is(TOKEN_LBRACE);
st->scope_ref = temp; // need to add to the parents scope
symbol_table_add(st, s);
st->scope_ref = (i32)st->count;
}
/**
* Branch.
*/
void define_branch(VM *vm, SymbolTable *st) {
void define_branch(VM *vm, ScopeTable *st) {
Symbol s;
s.scope = LOCAL;
s.type = VOID;
@ -702,7 +722,8 @@ int get_instruction_byte_size(const char *opname) {
}
#define FAKE_OP(op) \
} else if (strleq(token.start, op, token.length)) { \
} \
else if (strleq(token.start, op, token.length)) { \
do { \
while (token.type != TOKEN_SEMICOLON) { \
token = next_token(); \
@ -716,7 +737,7 @@ int get_instruction_byte_size(const char *opname) {
/**
* Build the symbol table and calculate the types/size/offsets of all values.
*/
void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
void build_symbol_table(VM *vm, char *source, ScopeTable *st) {
Token token;
init_lexer(source);
do {
@ -727,6 +748,22 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
}
if (token.type != TOKEN_EOF) {
if (token.type == TOKEN_LBRACE) {
st->count++;
st->scopes[st->count].parent = st->scope_ref;
st->scope_ref = (i32)st->count;
continue;
}
if (token.type == TOKEN_RBRACE) {
i32 current_scope = st->scope_ref;
i32 parent = st->scopes[current_scope].parent;
if (parent < 0) parent = 0;
st->scope_ref = parent;
continue;
}
if (token.type == TOKEN_KEYWORD_GLOBAL) {
define_global(vm, st);
continue;
@ -931,7 +968,7 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
/**
* 2nd pass, emit the bytecode
*/
void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
void emit_bytecode(VM *vm, char *source, ScopeTable *st) {
Token token;
init_lexer(source);
do {
@ -941,6 +978,21 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
break;
}
if (token.type != TOKEN_EOF) {
if (token.type == TOKEN_LBRACE) {
st->count++;
st->scopes[st->count].parent = st->scope_ref;
st->scope_ref = (i32)st->count;
continue;
}
if (token.type == TOKEN_RBRACE) {
i32 current_scope = st->scope_ref;
i32 parent = st->scopes[current_scope].parent;
if (parent < 0) parent = 0;
st->scope_ref = parent;
continue;
}
if (token.type == TOKEN_KEYWORD_GLOBAL) {
/* ignore, already processed */
@ -2417,8 +2469,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
/**
* Emit bytecode to the VM from the source string.
*/
void assemble(VM *vm, SymbolTable *st, char *source) {
void assemble(VM *vm, ScopeTable *st, char *source) {
build_symbol_table(vm, source, st);
vm->cp = 0; /* actually start emitting code */
st->count = 0;
emit_bytecode(vm, source, st);
}

View File

@ -26,6 +26,8 @@ typedef enum {
typedef struct symbol_s Symbol;
typedef struct symbol_tab_s SymbolTable;
typedef struct scope_tab_s ScopeTable;
typedef struct assembler_s Assembler;
#define MAX_SYMBOL_NAME_LENGTH 64
struct symbol_s {
@ -38,13 +40,20 @@ struct symbol_s {
};
struct symbol_tab_s {
Symbol *symbols;
u32 count;
u32 capacity;
Symbol symbols[256];
u8 count;
i32 parent;
};
void assemble(VM *vm, SymbolTable *st, char *source);
extern bool resize_or_check_size(SymbolTable *table);/* implement this in arch/ not here */
struct scope_tab_s {
SymbolTable *scopes;
u32 count;
u32 capacity;
i32 scope_ref;
};
void assemble(VM *vm, ScopeTable *st, char *source);
extern bool table_realloc(ScopeTable *table);/* implement this in arch/ not here */
const char *opcode_to_string(Opcode op);

View File

@ -3,188 +3,18 @@
#include "../../vm/common.h"
#include "../../vm/opcodes.h"
#include "../../vm/libc.h"
#include "../../vm/fixed.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
NamesTable *names_table_init() {
NamesTable *table = malloc(sizeof(NamesTable));
table->names = malloc(16 * sizeof(char *));
table->count = 0;
table->capacity = 16;
return table;
}
FunctionTable *function_table_init() {
FunctionTable *table = malloc(sizeof(FunctionTable));
table->symbols = malloc(16 * sizeof(FunctionDef));
table->count = 0;
table->capacity = 16;
return table;
}
ArrayTable *array_table_init() {
ArrayTable *table = malloc(sizeof(ArrayTable));
table->symbols = malloc(16 * sizeof(ArrayDef));
table->count = 0;
table->capacity = 16;
return table;
}
PlexTable *plex_table_init() {
PlexTable *table = malloc(sizeof(PlexTable));
table->symbols = malloc(16 * sizeof(PlexDef));
table->count = 0;
table->capacity = 16;
return table;
}
PlexFieldsTable *plex_fields_table_init() {
PlexFieldsTable *table = malloc(sizeof(PlexFieldsTable));
table->plex_refs = malloc(64 * sizeof(u32));
table->fields = malloc(64 * sizeof(ValueType));
table->count = 0;
table->capacity = 64;
return table;
}
u32 names_table_add(NamesTable *table, const char *name) {
for (u32 i = 0; i < table->count; i++) {
if (strcmp(table->names[i], name) == 0) {
return (u32)i;
}
}
if (table->count >= table->capacity) {
table->capacity *= 2;
table->names = realloc(table->names, table->capacity * sizeof(char *));
}
table->names[table->count] = malloc(strlen(name) + 1);
strcpy(table->names[table->count], name);
u32 index = (u32)table->count;
table->count++;
return index;
}
u32 function_table_add(FunctionTable *table, FunctionDef def) {
if (table->count >= table->capacity) {
table->capacity *= 2;
table->symbols =
realloc(table->symbols, table->capacity * sizeof(FunctionDef));
}
table->symbols[table->count] = def;
u32 index = (u32)table->count;
table->count++;
return index;
}
u32 array_table_add(ArrayTable *table, ArrayDef def) {
if (table->count >= table->capacity) {
table->capacity *= 2;
table->symbols = realloc(table->symbols, table->capacity * sizeof(ArrayDef));
}
table->symbols[table->count] = def;
u32 index = (u32)table->count;
table->count++;
return index;
}
u32 plex_add(PlexTable *plex_table, u32 name, u32 size, u32 field_start,
u32 field_count) {
if (plex_table->count >= plex_table->capacity) {
plex_table->capacity *= 2;
plex_table->symbols =
realloc(plex_table->symbols, plex_table->capacity * sizeof(PlexDef));
}
plex_table->symbols[plex_table->count].name = name;
plex_table->symbols[plex_table->count].size = size;
plex_table->symbols[plex_table->count].field_ref_start = field_start;
plex_table->symbols[plex_table->count].field_count = field_count;
u32 index = (u32)plex_table->count;
plex_table->count++;
return index;
}
u32 plex_fields_add(PlexFieldsTable *fields_table, u32 plex_ref,
ValueType field) {
if (fields_table->count + 1 > fields_table->capacity) {
u32 new_capacity = fields_table->capacity * 2;
if (new_capacity < fields_table->count + 1) {
new_capacity = fields_table->count + 1;
}
fields_table->plex_refs =
realloc(fields_table->plex_refs, new_capacity * sizeof(u32));
fields_table->fields =
realloc(fields_table->fields, new_capacity * sizeof(ValueType));
fields_table->capacity = new_capacity;
}
u32 start_index = fields_table->count;
fields_table->plex_refs[start_index] = plex_ref;
fields_table->fields[start_index] = field;
fields_table->count++;
return start_index;
}
int plex_get_field_index_by_name(PlexTable *plex_table,
PlexFieldsTable *fields_table,
NamesTable *names_table, u32 plex_index,
const char *field_name) {
if (plex_index >= plex_table->count)
return -1;
PlexDef *plex_def = &plex_table->symbols[plex_index];
u32 field_start = plex_def->field_ref_start;
u32 field_count = plex_def->field_count;
for (u32 i = 0; i < field_count; i++) {
u32 field_table_index = field_start + i;
ValueType *field = &fields_table->fields[field_table_index];
if (field->name < names_table->count) {
if (strcmp(names_table->names[field->name], field_name) == 0) {
return (int)i; // Return field index within the plex
}
}
}
return -1; // Not found
}
ValueType *plex_get_field(PlexTable *plex_table, PlexFieldsTable *fields_table,
u32 plex_index, u32 field_in_plex_index) {
if (plex_index >= plex_table->count)
return nil;
PlexDef *plex_def = &plex_table->symbols[plex_index];
if (field_in_plex_index >= plex_def->field_count)
return nil;
u32 field_table_index = plex_def->field_ref_start + field_in_plex_index;
return &fields_table->fields[field_table_index];
}
ValueType *plex_get_field_by_name(PlexTable *plex_table,
PlexFieldsTable *fields_table,
NamesTable *names_table, u32 plex_index,
const char *field_name) {
int field_index = plex_get_field_index_by_name(
plex_table, fields_table, names_table, plex_index, field_name);
if (field_index == -1)
return nil;
return plex_get_field(plex_table, fields_table, plex_index, (u32)field_index);
}
typedef struct {
Token current;
Token previous;
Token before;
bool hadError;
bool panicMode;
i8 rp;
} Parser;
typedef enum {
@ -209,13 +39,6 @@ typedef struct {
Precedence precedence;
} ParseRule;
typedef struct {
SymbolTable table;
Symbol current;
Symbol last;
i8 rp; // Next free register
} Compiler;
Parser parser;
const char *internalErrorMsg =
@ -269,30 +92,24 @@ void consume(TokenType type, const char *message) {
errorAtCurrent(message);
}
static int allocateRegister(Compiler *c) {
static int allocateRegister() {
char buffer[38];
if (c->rp + 1 > 31) {
sprintf(buffer, "Out of registers (used %d, max 32)", c->rp + 1);
if (parser.rp + 1 > 31) {
sprintf(buffer, "Out of registers (used %d, max 32)", parser.rp + 1);
error(buffer);
return -1;
}
return c->rp++;
return parser.rp++;
}
static void popRegister(Compiler *c) {
if (c->rp - 1 > 0) {
c->rp--;
static void popRegister() {
if (parser.rp - 1 > 0) {
parser.rp--;
}
}
static void freeRegister(Compiler *c, u8 reg) {
if (reg == c->rp - 1) {
c->rp--;
}
}
static void clearRegisters(Compiler *c, u8 reg) { c->rp = 0; }
static void clearRegisters(u8 reg) { parser.rp = 0; }
void emit_byte(VM *vm, u8 byte) { vm->code[vm->cp++] = byte; }
@ -312,20 +129,17 @@ static bool match(TokenType type) {
return true;
}
static void expression(Compiler *c, VM *vm) {
USED(c);
static void expression(VM *vm) {
USED(vm);
}
void number(Compiler *c, VM *vm) {
void number(VM *vm) {
emit_opcode(vm, OP_LOAD_IMM);
int reg = allocateRegister(c);
int reg = allocateRegister();
if (reg < 0)
return;
emit_byte(vm, reg);
c->last = Symbol{ .type=parser.previous.type };
switch (parser.previous.type) {
case TOKEN_LITERAL_INT: {
char *endptr;
@ -351,16 +165,16 @@ void number(Compiler *c, VM *vm) {
errorAtCurrent("Invalid number format");
}
static void unary(Compiler *c, VM *vm) {
static void unary(VM *vm) {
TokenType operatorType = parser.previous.type;
// Compile the operand.
expression(c, vm);
expression(vm);
// Emit the operator instruction.
switch (operatorType) {
case TOKEN_MINUS: {
switch (c->last.type) {
switch (parser.previous.type) {
case TOKEN_LITERAL_NAT:
emit_opcode(vm, OP_NEG_NAT);
case TOKEN_LITERAL_REAL:
@ -378,16 +192,16 @@ static void unary(Compiler *c, VM *vm) {
}
}
static void emitHalt(Compiler *c, VM *vm) {
static void emitHalt(VM *vm) {
emit_opcode(vm, OP_EXIT);
advance();
number(c, vm);
number(vm);
}
static void endCompiler(Compiler *c, VM *vm) { emitHalt(c, vm); }
static void endCompiler(VM *vm) { emitHalt(vm); }
static void grouping(Compiler *c, VM *vm) {
expression(c, vm);
static void grouping(VM *vm) {
expression(vm);
consume(TOKEN_RPAREN, "Expect ')' after expression.");
}
@ -399,11 +213,10 @@ bool compile(const char *source, VM *vm) {
parser.hadError = false;
parser.panicMode = false;
Compiler compiler;
advance();
expression(&compiler, vm);
expression(vm);
consume(TOKEN_EOF, "Expect end of expression.");
endCompiler(&compiler, vm);
endCompiler(vm);
return parser.hadError;
}

View File

@ -1,7 +1,7 @@
#include <string.h>
#include "../../vm/common.h"
#include "lexer.h"
#include "parser.h"
typedef struct {
const char *start;

View File

@ -16,6 +16,8 @@ typedef enum {
TOKEN_TYPE_NAT,
TOKEN_TYPE_REAL,
TOKEN_TYPE_STR,
TOKEN_TYPE_BOOL,
TOKEN_TYPE_VOID,
TOKEN_KEYWORD_PLEX,
TOKEN_KEYWORD_FN,
TOKEN_KEYWORD_CONST,
@ -35,6 +37,8 @@ typedef enum {
TOKEN_KEYWORD_WRITE,
TOKEN_KEYWORD_REFRESH,
TOKEN_KEYWORD_CLOSE,
TOKEN_KEYWORD_LOOP,
TOKEN_KEYWORD_DO,
TOKEN_KEYWORD_NIL,
TOKEN_KEYWORD_TRUE,
TOKEN_KEYWORD_FALSE,

View File

@ -3,20 +3,22 @@ global str new_line = "\n";
global int x = 1;
global int y = 1;
function main ()
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;
}
function add (int a $0, int b $1)
function add (int a $0, int b $1) {
int result $2;
add_int a b -> result;
return result;
}
function pln (str message $0)
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -33,3 +35,4 @@ function pln (str message $0)
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
}

View File

@ -1,7 +1,7 @@
global str terminal_namespace = "/dev/term/0";
global str new_line = "\n";
function main ()
function main () {
int str_n $1;
load_immediate 35 -> $0;
@ -9,8 +9,9 @@ function main ()
int_to_string $0 -> str_n;
call pln (str_n);
exit 0;
}
function fib (int n $0)
function fib (int n $0) {
load_immediate 2 -> $1;
jump_lt_int base_case n $1;
@ -28,8 +29,9 @@ function fib (int n $0)
else base_case;
return n;
}
function pln (str message $0)
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -46,4 +48,4 @@ function pln (str message $0)
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
}

View File

@ -2,14 +2,15 @@ global str terminal_namespace = "/dev/term/0";
global str new_line = "\n";
global str hello = "nuqneH 'u'?";
function main ()
function main () {
str msg $0;
load_address hello -> msg;
call pln (msg);
exit 0;
}
function pln (str message $0)
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -25,4 +26,5 @@ function pln (str message $0)
load_address new_line -> nl;
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
return;
}

View File

@ -2,36 +2,38 @@ global str terminal_namespace = "/dev/term/0";
global str prompt = "Enter a string:";
global str new_line = "\n";
function main ()
function main () {
real a $0;
int i $1;
int in_mode $11;
str in_term $10;
int mode $11;
str term $10;
// 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
loop loop_body {
add_real a $5 -> a;
add_int i $3 -> i;
jump_ge_int loop_body i $2;
jump_ge_int loop_body i $2;
}
load_address terminal_namespace -> in_term;
load_immediate 0 -> in_mode;
syscall OPEN in_term in_mode in_term; // Terminal term = open("/dev/term/0", 0);
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 in_term $7 $8; // print prompt
syscall WRITE term $7 $8; // print prompt
str user_string $9;
load_immediate 32 -> $8;
malloc $8 -> user_string;
syscall READ in_term user_string $8; // read in max 32 byte string
syscall READ term user_string $8; // read in max 32 byte string
call pln (user_string);
nat_to_string b -> $4;
@ -39,8 +41,9 @@ function main ()
real_to_string a -> $3;
call pln ($3);
exit 0;
}
function pln (str message $0)
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -56,3 +59,4 @@ function pln (str message $0)
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
}

View File

@ -2,27 +2,28 @@ global str terminal_namespace = "/dev/term/0";
global str prompt = "Enter a string:";
global str new_line = "\n";
function main ()
int in_mode $11;
str in_term $10;
function main () {
int mode $11;
str term $10;
load_address terminal_namespace -> in_term;
load_immediate 0 -> in_mode;
syscall OPEN in_term in_mode in_term; // Terminal term = open("/dev/term/0", 0);
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 in_term $7 $8; // print prompt
syscall WRITE term $7 $8; // print prompt
str user_string $9;
load_immediate 32 -> $8;
malloc $8 -> user_string;
syscall READ in_term user_string $8; // read in max 32 byte string
syscall READ term user_string $8; // read in max 32 byte string
call pln (user_string);
exit 0;
}
function pln (str message $0)
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -39,4 +40,4 @@ function pln (str message $0)
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
}

View File

@ -7,7 +7,7 @@ global byte GRAY = 146;
global byte LIGHT_GRAY = 182;
global byte SELECTED_COLOR = 255;
function main ()
function main () {
// Open screen
plex screen $0;
str screen_name $18;
@ -51,7 +51,7 @@ function main ()
nat m_zero $11;
loop draw_loop
loop draw_loop {
// load mouse click data
syscall REFRESH mouse;
@ -92,13 +92,14 @@ function main ()
call draw_box (screen_buffer width selected_color mouse_x mouse_y brush_size brush_size);
jump draw_loop;
jump draw_loop;
}
// Flush and exit
exit 0;
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)
int box_x $2, int box_y $3, byte check_color $4, int bsize $5) {
// Compute right
int right_edge $6;
@ -118,9 +119,10 @@ function set_color_if_clicked (int click_x $0, int click_y $1,
else fail
return;
}
function draw_outlined_swatch(nat dos_base $0,
byte swatch_color $1, int x $2, int y $3, int dos_width $4)
byte swatch_color $1, int x $2, int y $3, int dos_width $4) {
// Constants
nat background_color $5;
@ -152,10 +154,11 @@ function draw_outlined_swatch(nat dos_base $0,
call draw_box (dos_base dos_width swatch_color $9 $10 fill_size fill_size);
return;
}
function draw_box (nat db_base $0, nat screen_width $1,
byte box_color $2, nat x_start $3, nat y_start $4,
nat db_width $5, nat height $6)
nat db_width $5, nat height $6) {
// Compute start address: base + y*640 + x
nat offset $15;
@ -172,9 +175,11 @@ function draw_box (nat db_base $0, nat screen_width $1,
int zero $26;
load_immediate 0 -> zero;
loop draw_box_outer
loop draw_box_outer {
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;
jump_gt_int draw_box_outer height zero;
}
return;
}

View File

@ -34,7 +34,7 @@ global byte DARK_ORANGE = 208;
global byte GOLD = 244;
global byte SELECTED_COLOR = 255;
function main ()
function main () {
// Open screen
plex screen $0;
str screen_name $18;
@ -118,14 +118,14 @@ function main ()
nat m_zero $11;
loop draw_loop
loop draw_loop {
// load mouse click data
syscall REFRESH mouse;
byte left_down $9;
load_offset_8 mouse 16 -> left_down; // load btn1 pressed
jump_eq_nat draw_loop left_down m_zero;
jump_eq_nat draw_loop left_down m_zero; // if (!btn1.left) continue;
nat mouse_x $7;
nat mouse_y $8;
@ -206,13 +206,15 @@ function main ()
call draw_box (screen_buffer width selected_color mouse_x mouse_y brush_size brush_size);
jump draw_loop;
jump draw_loop;
}
// Flush and exit
exit 0;
}
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)
int box_x $2, int box_y $3, byte check_color $4, int bsize $5) {
// Compute right
int right_edge $6;
@ -232,9 +234,10 @@ function set_color_if_clicked (int click_x $0, int click_y $1,
else fail
return;
}
function draw_outlined_swatch(nat dos_base $0,
byte swatch_color $1, int x $2, int y $3, int dos_width $4)
byte swatch_color $1, int x $2, int y $3, int dos_width $4) {
// Constants
nat background_color $5;
@ -266,10 +269,11 @@ function draw_outlined_swatch(nat dos_base $0,
call draw_box (dos_base dos_width swatch_color $9 $10 fill_size fill_size);
return;
}
function draw_box (nat db_base $0, nat screen_width $1,
byte box_color $2, nat x_start $3, nat y_start $4,
nat db_width $5, nat height $6)
nat db_width $5, nat height $6) {
// Compute start address: base + y*640 + x
nat offset $15;
@ -286,9 +290,11 @@ function draw_box (nat db_base $0, nat screen_width $1,
int zero $26;
load_immediate 0 -> zero;
loop draw_box_outer
loop draw_box_outer {
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;
jump_gt_int draw_box_outer height zero;
}
return;
}

View File

@ -1,15 +1,16 @@
global str terminal_namespace = "/dev/term/0";
global str new_line = "\n";
function main ()
function main () {
load_immediate 1.0 -> $0;
load_immediate 2.0 -> $1;
add_real $0 $1 -> $0;
real_to_string $0 -> $0;
call pln ($0);
exit 0;
}
function pln (str message $0)
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -26,3 +27,4 @@ function pln (str message $0)
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
}

View File

@ -4,7 +4,7 @@ global str terminal_namespace = "/dev/term/0";
global str new_line = "\n";
global byte WHITE = 255;
function main ()
function main () {
plex screen $0;
plex mouse $1;
str tmp_str $2;
@ -47,13 +47,13 @@ function main ()
syscall WRITE screen screen_buffer buffer_size; // redraw
loop draw_loop
loop draw_loop {
// load mouse click data
syscall REFRESH mouse;
load_offset_8 mouse 16 -> left_down;
jump_eq_nat draw_loop left_down mode; // mode = 0 / false
jump_eq_nat draw_loop left_down mode; // if (!left_down) continue;
load_offset_32 mouse 8 -> x;
load_offset_32 mouse 12 -> y;
@ -70,10 +70,13 @@ function main ()
syscall WRITE screen screen_buffer buffer_size; // redraw
jump draw_loop;
exit 0;
jump draw_loop;
}
function pln (str message $0)
exit 0;
}
function pln (str message $0) {
plex term $1;
int msg_length $2;
str nl $3;
@ -90,3 +93,4 @@ function pln (str message $0)
string_length nl -> nl_length;
syscall WRITE term nl nl_length;
return;
}