Update assembler to add scopes
This commit is contained in:
parent
0fd2656704
commit
4114812146
|
|
@ -89,7 +89,7 @@ void mainloop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int cycles_this_frame = 0;
|
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) {
|
while (cycles_this_frame < max_cycles_per_frame) {
|
||||||
if (!step_vm(&vm)) {
|
if (!step_vm(&vm)) {
|
||||||
emscripten_cancel_main_loop();
|
emscripten_cancel_main_loop();
|
||||||
|
|
|
||||||
|
|
@ -130,24 +130,29 @@ bool compileAndSave(const char *source_file, const char *output_file, VM *vm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STATIC
|
#ifdef STATIC
|
||||||
#define SYMBOLS_COUNT 2048
|
#define SCOPES_COUNT 2048
|
||||||
Symbol symbols[SYMBOLS_COUNT];
|
SymbolTable scopes[SCOPES_COUNT];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void symbol_table_init(SymbolTable *t) {
|
void symbol_table_init(ScopeTable *t) {
|
||||||
#ifdef STATIC
|
#ifdef STATIC
|
||||||
memset(symbols, 0, SYMBOLS_COUNT*sizeof(Symbol));
|
memset(scopes, 0, SCOPES_COUNT*sizeof(SymbolTable));
|
||||||
t->symbols = symbols;
|
t->scopes = scopes;
|
||||||
t->count = 0;
|
t->count = 0;
|
||||||
t->capacity = SYMBOLS_COUNT;
|
t->capacity = SCOPES_COUNT;
|
||||||
#else
|
#else
|
||||||
t->symbols = calloc(16, sizeof(Symbol));
|
t->scopes = calloc(16, sizeof(SymbolTable));
|
||||||
t->count = 0;
|
t->count = 0;
|
||||||
t->capacity = 16;
|
t->capacity = 16;
|
||||||
#endif
|
#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
|
#ifdef STATIC
|
||||||
if (table->count >= table->capacity) {
|
if (table->count >= table->capacity) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -155,7 +160,12 @@ bool resize_or_check_size(SymbolTable *table) {
|
||||||
#else
|
#else
|
||||||
if (table->count >= table->capacity) {
|
if (table->count >= table->capacity) {
|
||||||
table->capacity *= 2;
|
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
|
#endif
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -183,11 +193,11 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) {
|
||||||
source[read] = '\0';
|
source[read] = '\0';
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
SymbolTable table = {0};
|
ScopeTable table = {0};
|
||||||
symbol_table_init(&table);
|
symbol_table_init(&table);
|
||||||
assemble(vm, &table, source);
|
assemble(vm, &table, source);
|
||||||
#ifndef STATIC
|
#ifndef STATIC
|
||||||
free(table.symbols);
|
free(table.scopes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (output_file) {
|
if (output_file) {
|
||||||
|
|
|
||||||
|
|
@ -162,29 +162,40 @@ void emit_u32(VM *vm, u32 value) {
|
||||||
write_u32(vm, code, vm->cp, value);
|
write_u32(vm, code, vm->cp, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *symbol_table_lookup(SymbolTable *table, const char *name, u32 length) {
|
Symbol *symbol_table_lookup(ScopeTable *table, const char *name, u32 length,
|
||||||
for (u32 i = 0; i < table->count; i++) {
|
i32 scope_ref) {
|
||||||
if (table->symbols[i].name_length == length) {
|
SymbolTable st = table->scopes[scope_ref];
|
||||||
if (strleq(table->symbols[i].name, name, length)) {
|
for (u32 i = 0; i < st.count; i++) {
|
||||||
return &table->symbols[i];
|
if (st.symbols[i].name_length == length) {
|
||||||
|
if (strleq(st.symbols[i].name, name, length)) {
|
||||||
|
return &table->scopes[scope_ref].symbols[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (st.parent < 0)
|
||||||
return nil;
|
return nil;
|
||||||
|
return symbol_table_lookup(table, name, length, st.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 symbol_table_add(SymbolTable *table, Symbol s) {
|
u8 symbol_table_add(ScopeTable *table, Symbol s) {
|
||||||
Symbol *sym = symbol_table_lookup(table, s.name, s.name_length);
|
Symbol *sym =
|
||||||
|
symbol_table_lookup(table, s.name, s.name_length, table->scope_ref);
|
||||||
if (sym != nil) {
|
if (sym != nil) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: Symbol '%.*s' already defined, the assembler is not smart "
|
"Error: Symbol '%.*s' already defined, in this scope"
|
||||||
"enough to do scope properly so please pick a different variable "
|
" please pick a different variable name or create a new scope.\n",
|
||||||
"name (hard I know)\n",
|
|
||||||
s.name_length, s.name);
|
s.name_length, s.name);
|
||||||
exit(1);
|
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,
|
fprintf(stderr,
|
||||||
"Error: Symbol table is out of memory! This is likely because you "
|
"Error: Symbol table is out of memory! This is likely because you "
|
||||||
" built the assembler in static mode, increase the static size."
|
" built the assembler in static mode, increase the static size."
|
||||||
|
|
@ -203,15 +214,14 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) {
|
||||||
printf("code[%d] = %s\n", s.ref, s.name);
|
printf("code[%d] = %s\n", s.ref, s.name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
table->scopes[table->scope_ref].symbols[table->scopes[table->scope_ref].count] = s;
|
||||||
table->symbols[table->count] = s;
|
u8 index = table->scopes[table->scope_ref].count;
|
||||||
u32 index = table->count;
|
table->scopes[table->scope_ref].count++;
|
||||||
table->count++;
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 get_ref(SymbolTable *st, const char *name, u32 length) {
|
u32 get_ref(ScopeTable *st, const char *name, u32 length) {
|
||||||
Symbol *sym = symbol_table_lookup(st, name, length);
|
Symbol *sym = symbol_table_lookup(st, name, length, st->scope_ref);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
fprintf(stderr, "Error: Assembler has no idea what Symbol '%.*s' means.\n",
|
fprintf(stderr, "Error: Assembler has no idea what Symbol '%.*s' means.\n",
|
||||||
length, name);
|
length, name);
|
||||||
|
|
@ -221,7 +231,7 @@ u32 get_ref(SymbolTable *st, const char *name, u32 length) {
|
||||||
return sym->ref;
|
return sym->ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 get_ptr(Token token, SymbolTable *st) {
|
u32 get_ptr(Token token, ScopeTable *st) {
|
||||||
if (token.type == TOKEN_IDENTIFIER) {
|
if (token.type == TOKEN_IDENTIFIER) {
|
||||||
return get_ref(st, token.start, token.length);
|
return get_ref(st, token.start, token.length);
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +256,7 @@ u32 get_ptr(Token token, SymbolTable *st) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 get_reg(Token token, SymbolTable *st) {
|
u32 get_reg(Token token, ScopeTable *st) {
|
||||||
if (token.type == TOKEN_IDENTIFIER) {
|
if (token.type == TOKEN_IDENTIFIER) {
|
||||||
return get_ref(st, token.start, token.length);
|
return get_ref(st, token.start, token.length);
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +313,7 @@ Token next_token_is(TokenType type) {
|
||||||
/**
|
/**
|
||||||
* Global .
|
* Global .
|
||||||
*/
|
*/
|
||||||
bool define_global(VM *vm, SymbolTable *st) {
|
bool define_global(VM *vm, ScopeTable *st) {
|
||||||
Symbol s;
|
Symbol s;
|
||||||
|
|
||||||
Token token_type = next_token();
|
Token token_type = next_token();
|
||||||
|
|
@ -472,7 +482,7 @@ bool define_global(VM *vm, SymbolTable *st) {
|
||||||
/**
|
/**
|
||||||
* Var .
|
* Var .
|
||||||
*/
|
*/
|
||||||
void define_var(SymbolTable *st, Token regType) {
|
void define_var(ScopeTable *st, Token regType) {
|
||||||
Symbol s;
|
Symbol s;
|
||||||
s.scope = VAR;
|
s.scope = VAR;
|
||||||
switch (regType.type) {
|
switch (regType.type) {
|
||||||
|
|
@ -553,7 +563,7 @@ void define_var(SymbolTable *st, Token regType) {
|
||||||
/**
|
/**
|
||||||
* function .
|
* function .
|
||||||
*/
|
*/
|
||||||
void define_function(VM *vm, SymbolTable *st) {
|
void define_function(VM *vm, ScopeTable *st) {
|
||||||
Symbol s;
|
Symbol s;
|
||||||
s.scope = LOCAL;
|
s.scope = LOCAL;
|
||||||
s.type = FUNCTION;
|
s.type = FUNCTION;
|
||||||
|
|
@ -570,6 +580,12 @@ void define_function(VM *vm, SymbolTable *st) {
|
||||||
|
|
||||||
next_token_is(TOKEN_LPAREN);
|
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();
|
Token next = next_token();
|
||||||
while (next.type != TOKEN_RPAREN) {
|
while (next.type != TOKEN_RPAREN) {
|
||||||
define_var(st, next);
|
define_var(st, next);
|
||||||
|
|
@ -585,13 +601,17 @@ void define_function(VM *vm, SymbolTable *st) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.ref = vm->cp;
|
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);
|
symbol_table_add(st, s);
|
||||||
|
st->scope_ref = (i32)st->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Branch.
|
* Branch.
|
||||||
*/
|
*/
|
||||||
void define_branch(VM *vm, SymbolTable *st) {
|
void define_branch(VM *vm, ScopeTable *st) {
|
||||||
Symbol s;
|
Symbol s;
|
||||||
s.scope = LOCAL;
|
s.scope = LOCAL;
|
||||||
s.type = VOID;
|
s.type = VOID;
|
||||||
|
|
@ -702,7 +722,8 @@ int get_instruction_byte_size(const char *opname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FAKE_OP(op) \
|
#define FAKE_OP(op) \
|
||||||
} else if (strleq(token.start, op, token.length)) { \
|
} \
|
||||||
|
else if (strleq(token.start, op, token.length)) { \
|
||||||
do { \
|
do { \
|
||||||
while (token.type != TOKEN_SEMICOLON) { \
|
while (token.type != TOKEN_SEMICOLON) { \
|
||||||
token = next_token(); \
|
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.
|
* 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;
|
Token token;
|
||||||
init_lexer(source);
|
init_lexer(source);
|
||||||
do {
|
do {
|
||||||
|
|
@ -727,6 +748,22 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.type != TOKEN_EOF) {
|
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) {
|
if (token.type == TOKEN_KEYWORD_GLOBAL) {
|
||||||
define_global(vm, st);
|
define_global(vm, st);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -931,7 +968,7 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
|
||||||
/**
|
/**
|
||||||
* 2nd pass, emit the bytecode
|
* 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;
|
Token token;
|
||||||
init_lexer(source);
|
init_lexer(source);
|
||||||
do {
|
do {
|
||||||
|
|
@ -942,6 +979,21 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
|
||||||
}
|
}
|
||||||
if (token.type != TOKEN_EOF) {
|
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) {
|
if (token.type == TOKEN_KEYWORD_GLOBAL) {
|
||||||
/* ignore, already processed */
|
/* ignore, already processed */
|
||||||
next_token(); /* type */
|
next_token(); /* type */
|
||||||
|
|
@ -2417,8 +2469,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
|
||||||
/**
|
/**
|
||||||
* Emit bytecode to the VM from the source string.
|
* 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);
|
build_symbol_table(vm, source, st);
|
||||||
vm->cp = 0; /* actually start emitting code */
|
vm->cp = 0; /* actually start emitting code */
|
||||||
|
st->count = 0;
|
||||||
emit_bytecode(vm, source, st);
|
emit_bytecode(vm, source, st);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct symbol_s Symbol;
|
typedef struct symbol_s Symbol;
|
||||||
typedef struct symbol_tab_s SymbolTable;
|
typedef struct symbol_tab_s SymbolTable;
|
||||||
|
typedef struct scope_tab_s ScopeTable;
|
||||||
|
typedef struct assembler_s Assembler;
|
||||||
|
|
||||||
#define MAX_SYMBOL_NAME_LENGTH 64
|
#define MAX_SYMBOL_NAME_LENGTH 64
|
||||||
struct symbol_s {
|
struct symbol_s {
|
||||||
|
|
@ -38,13 +40,20 @@ struct symbol_s {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct symbol_tab_s {
|
struct symbol_tab_s {
|
||||||
Symbol *symbols;
|
Symbol symbols[256];
|
||||||
u32 count;
|
u8 count;
|
||||||
u32 capacity;
|
i32 parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
void assemble(VM *vm, SymbolTable *st, char *source);
|
struct scope_tab_s {
|
||||||
extern bool resize_or_check_size(SymbolTable *table);/* implement this in arch/ not here */
|
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);
|
const char *opcode_to_string(Opcode op);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,188 +3,18 @@
|
||||||
#include "../../vm/common.h"
|
#include "../../vm/common.h"
|
||||||
#include "../../vm/opcodes.h"
|
#include "../../vm/opcodes.h"
|
||||||
#include "../../vm/libc.h"
|
#include "../../vm/libc.h"
|
||||||
|
#include "../../vm/fixed.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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 {
|
typedef struct {
|
||||||
Token current;
|
Token current;
|
||||||
Token previous;
|
Token previous;
|
||||||
|
Token before;
|
||||||
bool hadError;
|
bool hadError;
|
||||||
bool panicMode;
|
bool panicMode;
|
||||||
|
i8 rp;
|
||||||
} Parser;
|
} Parser;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -209,13 +39,6 @@ typedef struct {
|
||||||
Precedence precedence;
|
Precedence precedence;
|
||||||
} ParseRule;
|
} ParseRule;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SymbolTable table;
|
|
||||||
Symbol current;
|
|
||||||
Symbol last;
|
|
||||||
i8 rp; // Next free register
|
|
||||||
} Compiler;
|
|
||||||
|
|
||||||
Parser parser;
|
Parser parser;
|
||||||
|
|
||||||
const char *internalErrorMsg =
|
const char *internalErrorMsg =
|
||||||
|
|
@ -269,30 +92,24 @@ void consume(TokenType type, const char *message) {
|
||||||
errorAtCurrent(message);
|
errorAtCurrent(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int allocateRegister(Compiler *c) {
|
static int allocateRegister() {
|
||||||
char buffer[38];
|
char buffer[38];
|
||||||
if (c->rp + 1 > 31) {
|
if (parser.rp + 1 > 31) {
|
||||||
sprintf(buffer, "Out of registers (used %d, max 32)", c->rp + 1);
|
sprintf(buffer, "Out of registers (used %d, max 32)", parser.rp + 1);
|
||||||
error(buffer);
|
error(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return c->rp++;
|
return parser.rp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void popRegister(Compiler *c) {
|
static void popRegister() {
|
||||||
if (c->rp - 1 > 0) {
|
if (parser.rp - 1 > 0) {
|
||||||
c->rp--;
|
parser.rp--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeRegister(Compiler *c, u8 reg) {
|
static void clearRegisters(u8 reg) { parser.rp = 0; }
|
||||||
if (reg == c->rp - 1) {
|
|
||||||
c->rp--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clearRegisters(Compiler *c, u8 reg) { c->rp = 0; }
|
|
||||||
|
|
||||||
void emit_byte(VM *vm, u8 byte) { vm->code[vm->cp++] = byte; }
|
void emit_byte(VM *vm, u8 byte) { vm->code[vm->cp++] = byte; }
|
||||||
|
|
||||||
|
|
@ -312,20 +129,17 @@ static bool match(TokenType type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expression(Compiler *c, VM *vm) {
|
static void expression(VM *vm) {
|
||||||
USED(c);
|
|
||||||
USED(vm);
|
USED(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void number(Compiler *c, VM *vm) {
|
void number(VM *vm) {
|
||||||
emit_opcode(vm, OP_LOAD_IMM);
|
emit_opcode(vm, OP_LOAD_IMM);
|
||||||
int reg = allocateRegister(c);
|
int reg = allocateRegister();
|
||||||
if (reg < 0)
|
if (reg < 0)
|
||||||
return;
|
return;
|
||||||
emit_byte(vm, reg);
|
emit_byte(vm, reg);
|
||||||
|
|
||||||
c->last = Symbol{ .type=parser.previous.type };
|
|
||||||
|
|
||||||
switch (parser.previous.type) {
|
switch (parser.previous.type) {
|
||||||
case TOKEN_LITERAL_INT: {
|
case TOKEN_LITERAL_INT: {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
@ -351,16 +165,16 @@ void number(Compiler *c, VM *vm) {
|
||||||
errorAtCurrent("Invalid number format");
|
errorAtCurrent("Invalid number format");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unary(Compiler *c, VM *vm) {
|
static void unary(VM *vm) {
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser.previous.type;
|
||||||
|
|
||||||
// Compile the operand.
|
// Compile the operand.
|
||||||
expression(c, vm);
|
expression(vm);
|
||||||
|
|
||||||
// Emit the operator instruction.
|
// Emit the operator instruction.
|
||||||
switch (operatorType) {
|
switch (operatorType) {
|
||||||
case TOKEN_MINUS: {
|
case TOKEN_MINUS: {
|
||||||
switch (c->last.type) {
|
switch (parser.previous.type) {
|
||||||
case TOKEN_LITERAL_NAT:
|
case TOKEN_LITERAL_NAT:
|
||||||
emit_opcode(vm, OP_NEG_NAT);
|
emit_opcode(vm, OP_NEG_NAT);
|
||||||
case TOKEN_LITERAL_REAL:
|
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);
|
emit_opcode(vm, OP_EXIT);
|
||||||
advance();
|
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) {
|
static void grouping(VM *vm) {
|
||||||
expression(c, vm);
|
expression(vm);
|
||||||
consume(TOKEN_RPAREN, "Expect ')' after expression.");
|
consume(TOKEN_RPAREN, "Expect ')' after expression.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -399,11 +213,10 @@ bool compile(const char *source, VM *vm) {
|
||||||
parser.hadError = false;
|
parser.hadError = false;
|
||||||
parser.panicMode = false;
|
parser.panicMode = false;
|
||||||
|
|
||||||
Compiler compiler;
|
|
||||||
advance();
|
advance();
|
||||||
expression(&compiler, vm);
|
expression(vm);
|
||||||
consume(TOKEN_EOF, "Expect end of expression.");
|
consume(TOKEN_EOF, "Expect end of expression.");
|
||||||
endCompiler(&compiler, vm);
|
endCompiler(vm);
|
||||||
|
|
||||||
return parser.hadError;
|
return parser.hadError;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../../vm/common.h"
|
#include "../../vm/common.h"
|
||||||
#include "lexer.h"
|
#include "parser.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *start;
|
const char *start;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ typedef enum {
|
||||||
TOKEN_TYPE_NAT,
|
TOKEN_TYPE_NAT,
|
||||||
TOKEN_TYPE_REAL,
|
TOKEN_TYPE_REAL,
|
||||||
TOKEN_TYPE_STR,
|
TOKEN_TYPE_STR,
|
||||||
|
TOKEN_TYPE_BOOL,
|
||||||
|
TOKEN_TYPE_VOID,
|
||||||
TOKEN_KEYWORD_PLEX,
|
TOKEN_KEYWORD_PLEX,
|
||||||
TOKEN_KEYWORD_FN,
|
TOKEN_KEYWORD_FN,
|
||||||
TOKEN_KEYWORD_CONST,
|
TOKEN_KEYWORD_CONST,
|
||||||
|
|
@ -35,6 +37,8 @@ typedef enum {
|
||||||
TOKEN_KEYWORD_WRITE,
|
TOKEN_KEYWORD_WRITE,
|
||||||
TOKEN_KEYWORD_REFRESH,
|
TOKEN_KEYWORD_REFRESH,
|
||||||
TOKEN_KEYWORD_CLOSE,
|
TOKEN_KEYWORD_CLOSE,
|
||||||
|
TOKEN_KEYWORD_LOOP,
|
||||||
|
TOKEN_KEYWORD_DO,
|
||||||
TOKEN_KEYWORD_NIL,
|
TOKEN_KEYWORD_NIL,
|
||||||
TOKEN_KEYWORD_TRUE,
|
TOKEN_KEYWORD_TRUE,
|
||||||
TOKEN_KEYWORD_FALSE,
|
TOKEN_KEYWORD_FALSE,
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,22 @@ global str new_line = "\n";
|
||||||
global int x = 1;
|
global int x = 1;
|
||||||
global int y = 1;
|
global int y = 1;
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
load_absolute_32 x -> $0;
|
load_absolute_32 x -> $0;
|
||||||
load_absolute_32 y -> $1;
|
load_absolute_32 y -> $1;
|
||||||
call add ($0 $1) -> $2;
|
call add ($0 $1) -> $2;
|
||||||
int_to_string $2 -> $3;
|
int_to_string $2 -> $3;
|
||||||
call pln ($3);
|
call pln ($3);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function add (int a $0, int b $1)
|
function add (int a $0, int b $1) {
|
||||||
int result $2;
|
int result $2;
|
||||||
add_int a b -> result;
|
add_int a b -> result;
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -33,3 +35,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
global str terminal_namespace = "/dev/term/0";
|
global str terminal_namespace = "/dev/term/0";
|
||||||
global str new_line = "\n";
|
global str new_line = "\n";
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
int str_n $1;
|
int str_n $1;
|
||||||
|
|
||||||
load_immediate 35 -> $0;
|
load_immediate 35 -> $0;
|
||||||
|
|
@ -9,8 +9,9 @@ function main ()
|
||||||
int_to_string $0 -> str_n;
|
int_to_string $0 -> str_n;
|
||||||
call pln (str_n);
|
call pln (str_n);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function fib (int n $0)
|
function fib (int n $0) {
|
||||||
load_immediate 2 -> $1;
|
load_immediate 2 -> $1;
|
||||||
|
|
||||||
jump_lt_int base_case n $1;
|
jump_lt_int base_case n $1;
|
||||||
|
|
@ -28,8 +29,9 @@ function fib (int n $0)
|
||||||
|
|
||||||
else base_case;
|
else base_case;
|
||||||
return n;
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -46,4 +48,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@ global str terminal_namespace = "/dev/term/0";
|
||||||
global str new_line = "\n";
|
global str new_line = "\n";
|
||||||
global str hello = "nuqneH 'u'?";
|
global str hello = "nuqneH 'u'?";
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
str msg $0;
|
str msg $0;
|
||||||
|
|
||||||
load_address hello -> msg;
|
load_address hello -> msg;
|
||||||
call pln (msg);
|
call pln (msg);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -26,3 +27,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,36 +2,38 @@ global str terminal_namespace = "/dev/term/0";
|
||||||
global str prompt = "Enter a string:";
|
global str prompt = "Enter a string:";
|
||||||
global str new_line = "\n";
|
global str new_line = "\n";
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
real a $0;
|
real a $0;
|
||||||
int i $1;
|
int i $1;
|
||||||
int in_mode $11;
|
int mode $11;
|
||||||
str in_term $10;
|
str term $10;
|
||||||
|
|
||||||
|
// do (i = 5000; i >= 0, i = i - 1)
|
||||||
load_immediate 5.0 -> a;
|
load_immediate 5.0 -> a;
|
||||||
load_immediate 5000 -> i;
|
load_immediate 5000 -> i;
|
||||||
load_immediate 0 -> $2;
|
load_immediate 0 -> $2;
|
||||||
load_immediate -1 -> $3;
|
load_immediate -1 -> $3;
|
||||||
load_immediate 5.0 -> $5;
|
load_immediate 5.0 -> $5;
|
||||||
loop loop_body
|
loop loop_body {
|
||||||
add_real a $5 -> a;
|
add_real a $5 -> a;
|
||||||
add_int i $3 -> i;
|
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_address terminal_namespace -> term;
|
||||||
load_immediate 0 -> in_mode;
|
load_immediate 0 -> mode;
|
||||||
syscall OPEN in_term in_mode in_term; // Terminal term = open("/dev/term/0", 0);
|
syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0);
|
||||||
|
|
||||||
nat b $1;
|
nat b $1;
|
||||||
real_to_nat a -> b;
|
real_to_nat a -> b;
|
||||||
load_address prompt -> $7;
|
load_address prompt -> $7;
|
||||||
string_length $7 -> $8;
|
string_length $7 -> $8;
|
||||||
syscall WRITE in_term $7 $8; // print prompt
|
syscall WRITE term $7 $8; // print prompt
|
||||||
|
|
||||||
str user_string $9;
|
str user_string $9;
|
||||||
load_immediate 32 -> $8;
|
load_immediate 32 -> $8;
|
||||||
malloc $8 -> user_string;
|
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);
|
call pln (user_string);
|
||||||
nat_to_string b -> $4;
|
nat_to_string b -> $4;
|
||||||
|
|
@ -39,8 +41,9 @@ function main ()
|
||||||
real_to_string a -> $3;
|
real_to_string a -> $3;
|
||||||
call pln ($3);
|
call pln ($3);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -56,3 +59,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,28 @@ global str terminal_namespace = "/dev/term/0";
|
||||||
global str prompt = "Enter a string:";
|
global str prompt = "Enter a string:";
|
||||||
global str new_line = "\n";
|
global str new_line = "\n";
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
int in_mode $11;
|
int mode $11;
|
||||||
str in_term $10;
|
str term $10;
|
||||||
|
|
||||||
load_address terminal_namespace -> in_term;
|
load_address terminal_namespace -> term;
|
||||||
load_immediate 0 -> in_mode;
|
load_immediate 0 -> mode;
|
||||||
syscall OPEN in_term in_mode in_term; // Terminal term = open("/dev/term/0", 0);
|
syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0);
|
||||||
|
|
||||||
load_address prompt -> $7;
|
load_address prompt -> $7;
|
||||||
string_length $7 -> $8;
|
string_length $7 -> $8;
|
||||||
syscall WRITE in_term $7 $8; // print prompt
|
syscall WRITE term $7 $8; // print prompt
|
||||||
|
|
||||||
str user_string $9;
|
str user_string $9;
|
||||||
load_immediate 32 -> $8;
|
load_immediate 32 -> $8;
|
||||||
malloc $8 -> user_string;
|
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);
|
call pln (user_string);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -39,4 +40,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ global byte GRAY = 146;
|
||||||
global byte LIGHT_GRAY = 182;
|
global byte LIGHT_GRAY = 182;
|
||||||
global byte SELECTED_COLOR = 255;
|
global byte SELECTED_COLOR = 255;
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
// Open screen
|
// Open screen
|
||||||
plex screen $0;
|
plex screen $0;
|
||||||
str screen_name $18;
|
str screen_name $18;
|
||||||
|
|
@ -51,7 +51,7 @@ function main ()
|
||||||
|
|
||||||
nat m_zero $11;
|
nat m_zero $11;
|
||||||
|
|
||||||
loop draw_loop
|
loop draw_loop {
|
||||||
// load mouse click data
|
// load mouse click data
|
||||||
syscall REFRESH mouse;
|
syscall REFRESH mouse;
|
||||||
|
|
||||||
|
|
@ -93,12 +93,13 @@ function main ()
|
||||||
call 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_loop;
|
jump draw_loop;
|
||||||
|
}
|
||||||
|
|
||||||
// Flush and exit
|
// Flush and exit
|
||||||
exit 0;
|
exit 0;
|
||||||
|
|
||||||
function set_color_if_clicked (int click_x $0, int click_y $1,
|
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
|
// Compute right
|
||||||
int right_edge $6;
|
int right_edge $6;
|
||||||
|
|
@ -118,9 +119,10 @@ function set_color_if_clicked (int click_x $0, int click_y $1,
|
||||||
|
|
||||||
else fail
|
else fail
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function draw_outlined_swatch(nat dos_base $0,
|
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
|
// Constants
|
||||||
nat background_color $5;
|
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);
|
call draw_box (dos_base dos_width swatch_color $9 $10 fill_size fill_size);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function draw_box (nat db_base $0, nat screen_width $1,
|
function draw_box (nat db_base $0, nat screen_width $1,
|
||||||
byte box_color $2, nat x_start $3, nat y_start $4,
|
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
|
// Compute start address: base + y*640 + x
|
||||||
nat offset $15;
|
nat offset $15;
|
||||||
|
|
@ -172,9 +175,11 @@ function draw_box (nat db_base $0, nat screen_width $1,
|
||||||
int zero $26;
|
int zero $26;
|
||||||
load_immediate 0 -> zero;
|
load_immediate 0 -> zero;
|
||||||
|
|
||||||
loop draw_box_outer
|
loop draw_box_outer {
|
||||||
memset_8 box_color db_width -> offset; // draw row
|
memset_8 box_color db_width -> offset; // draw row
|
||||||
add_int offset screen_width -> offset; // next row += 640
|
add_int offset screen_width -> offset; // next row += 640
|
||||||
sub_int height i -> height; // decrement row count
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
@ -34,7 +34,7 @@ global byte DARK_ORANGE = 208;
|
||||||
global byte GOLD = 244;
|
global byte GOLD = 244;
|
||||||
global byte SELECTED_COLOR = 255;
|
global byte SELECTED_COLOR = 255;
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
// Open screen
|
// Open screen
|
||||||
plex screen $0;
|
plex screen $0;
|
||||||
str screen_name $18;
|
str screen_name $18;
|
||||||
|
|
@ -118,14 +118,14 @@ function main ()
|
||||||
|
|
||||||
nat m_zero $11;
|
nat m_zero $11;
|
||||||
|
|
||||||
loop draw_loop
|
loop draw_loop {
|
||||||
// load mouse click data
|
// load mouse click data
|
||||||
syscall REFRESH mouse;
|
syscall REFRESH mouse;
|
||||||
|
|
||||||
byte left_down $9;
|
byte left_down $9;
|
||||||
load_offset_8 mouse 16 -> left_down; // load btn1 pressed
|
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_x $7;
|
||||||
nat mouse_y $8;
|
nat mouse_y $8;
|
||||||
|
|
@ -207,12 +207,14 @@ function main ()
|
||||||
call 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_loop;
|
jump draw_loop;
|
||||||
|
}
|
||||||
|
|
||||||
// Flush and exit
|
// Flush and exit
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function set_color_if_clicked (int click_x $0, int click_y $1,
|
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
|
// Compute right
|
||||||
int right_edge $6;
|
int right_edge $6;
|
||||||
|
|
@ -232,9 +234,10 @@ function set_color_if_clicked (int click_x $0, int click_y $1,
|
||||||
|
|
||||||
else fail
|
else fail
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function draw_outlined_swatch(nat dos_base $0,
|
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
|
// Constants
|
||||||
nat background_color $5;
|
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);
|
call draw_box (dos_base dos_width swatch_color $9 $10 fill_size fill_size);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function draw_box (nat db_base $0, nat screen_width $1,
|
function draw_box (nat db_base $0, nat screen_width $1,
|
||||||
byte box_color $2, nat x_start $3, nat y_start $4,
|
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
|
// Compute start address: base + y*640 + x
|
||||||
nat offset $15;
|
nat offset $15;
|
||||||
|
|
@ -286,9 +290,11 @@ function draw_box (nat db_base $0, nat screen_width $1,
|
||||||
int zero $26;
|
int zero $26;
|
||||||
load_immediate 0 -> zero;
|
load_immediate 0 -> zero;
|
||||||
|
|
||||||
loop draw_box_outer
|
loop draw_box_outer {
|
||||||
memset_8 box_color db_width -> offset; // draw row
|
memset_8 box_color db_width -> offset; // draw row
|
||||||
add_int offset screen_width -> offset; // next row += 640
|
add_int offset screen_width -> offset; // next row += 640
|
||||||
sub_int height i -> height; // decrement row count
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
global str terminal_namespace = "/dev/term/0";
|
global str terminal_namespace = "/dev/term/0";
|
||||||
global str new_line = "\n";
|
global str new_line = "\n";
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
load_immediate 1.0 -> $0;
|
load_immediate 1.0 -> $0;
|
||||||
load_immediate 2.0 -> $1;
|
load_immediate 2.0 -> $1;
|
||||||
add_real $0 $1 -> $0;
|
add_real $0 $1 -> $0;
|
||||||
real_to_string $0 -> $0;
|
real_to_string $0 -> $0;
|
||||||
call pln ($0);
|
call pln ($0);
|
||||||
exit 0;
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -26,3 +27,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ global str terminal_namespace = "/dev/term/0";
|
||||||
global str new_line = "\n";
|
global str new_line = "\n";
|
||||||
global byte WHITE = 255;
|
global byte WHITE = 255;
|
||||||
|
|
||||||
function main ()
|
function main () {
|
||||||
plex screen $0;
|
plex screen $0;
|
||||||
plex mouse $1;
|
plex mouse $1;
|
||||||
str tmp_str $2;
|
str tmp_str $2;
|
||||||
|
|
@ -47,13 +47,13 @@ function main ()
|
||||||
|
|
||||||
syscall WRITE screen screen_buffer buffer_size; // redraw
|
syscall WRITE screen screen_buffer buffer_size; // redraw
|
||||||
|
|
||||||
loop draw_loop
|
loop draw_loop {
|
||||||
// load mouse click data
|
// load mouse click data
|
||||||
syscall REFRESH mouse;
|
syscall REFRESH mouse;
|
||||||
|
|
||||||
load_offset_8 mouse 16 -> left_down;
|
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 8 -> x;
|
||||||
load_offset_32 mouse 12 -> y;
|
load_offset_32 mouse 12 -> y;
|
||||||
|
|
@ -71,9 +71,12 @@ function main ()
|
||||||
syscall WRITE screen screen_buffer buffer_size; // redraw
|
syscall WRITE screen screen_buffer buffer_size; // redraw
|
||||||
|
|
||||||
jump draw_loop;
|
jump draw_loop;
|
||||||
exit 0;
|
}
|
||||||
|
|
||||||
function pln (str message $0)
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pln (str message $0) {
|
||||||
plex term $1;
|
plex term $1;
|
||||||
int msg_length $2;
|
int msg_length $2;
|
||||||
str nl $3;
|
str nl $3;
|
||||||
|
|
@ -90,3 +93,4 @@ function pln (str message $0)
|
||||||
string_length nl -> nl_length;
|
string_length nl -> nl_length;
|
||||||
syscall WRITE term nl nl_length;
|
syscall WRITE term nl nl_length;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue