language

Some fools attempt at an interpreted language
Log | Files | Refs

commit 6fa3e5edebab3a6535e664aba447ae1dad7c77fe
parent 8ad809648fed5219c2b6a5face7902f1efe9465c
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Tue May  3 14:07:46 2016

More object. More work that needs to be done.

Diffstat:
 doc/SPECIFICATION          |   6 +-
 src/lc/bytecode.py         | 122 ++++++++++++++++++++++++++--------------------
 src/lc/interpreter.py      |  25 +++++++--
 src/lc/memonic.py          |   1 +-
 src/lc/parser.py           |  40 ++++++++++-----
 src/lc/test_files/class.ti |  41 ++++++++++++---
 src/lc/test_files/fibb.ti  |  15 +------
 src/lc/test_files/if.ti    |   4 +--
 src/lc/test_files/test.ti  |   4 +-
 src/vm/inc/ins_def.h       |   1 +-
 src/vm/inc/ins_mdata.h     |  18 ++++---
 src/vm/inc/rt.h            |   1 +-
 src/vm/src/ins_def.c       |  22 +++++---
 src/vm/src/main.c          |   2 +-
 src/vm/src/pc.c            |   2 +-
 src/vm/src/proc.c          |  11 ++--
 src/vm/src/var.c           |   5 ++-
 17 files changed, 201 insertions(+), 119 deletions(-)

diff --git a/doc/SPECIFICATION b/doc/SPECIFICATION @@ -312,9 +312,9 @@ F0 RETURN - Returns from function 01 LC N<name> - Calls OS function library, i.e. I/O, opening files, etc TBI -02 PRINT - Prints whatever is on the TOS. TBI +02 PRINT - Prints whatever is on the TOS. -03 FREE - Pops & Deletes TOS +03 DEBUG - Toggle debug mode 0E ARGB - Builds arguement stack @@ -322,7 +322,7 @@ F0 RETURN - Returns from function primitive subroutines providing methods to tweak objects this bytecode set cannot touch. Uses argstack. _______________________________________________________________________________ -COMPILER/TRANSLATOR/ASSEMBLER SHINDIGS +COMPILER/TRANSLATOR/ASSEMBLER -------------------------------------------------------------------------------- LEXICAL ANALYSIS diff --git a/src/lc/bytecode.py b/src/lc/bytecode.py @@ -1,54 +1,9 @@ from memonic import * from helper import * -class VariableNew(): - def __init__(self, label, typed): - self.label = label - self.typed = typed - - def action(self): - return([ - OP_DEC, - self.label.action(s=True), - self.typed.action(), - self.label.action() - ]) - -class VariableAssignment(): - def __init__(self, label, expression): - self.label = label - self.expr = expression - - def action(self): - if self.label.is_property: - return(PropertyAssignment(self.label.obj, - self.label, - self.expr).action()) - else: - return([ - self.expr.action(), - OP_STV, - self.label.action(s=True), - self.label.action() - ]) - -class VariableGet(): - def __init__(self, label): - self.label = label - - def action(self): - if self.label.is_property: - return(PropertyGet(self.label.obj, self.label).action()) - else: - return([ - OP_LOV, - self.label.action(s=True), - self.label.action() - ]) - class PropertyAssignment(): def __init__(self, ovar, plabel, expression): - self.ovar = ovar + self.ovar = VariableGet(ovar) self.label = plabel self.expr = expression @@ -72,6 +27,20 @@ class PropertyGet(): self.label.action() ]) +class MethodCall(): + def __init__(self, ovar, label, arguements): + self.ovar = VariableGet(ovar) + self.label = label + self.args = arguements + + def action(self): + return([ + self.args.action(), + self.ovar.action(), + OP_CALLM, + self.label.action() + ]) + class ClassDef(): def __init__(self, label, args): self.label = label @@ -98,12 +67,58 @@ class NewClass(): self.label.action(), OP_DEC, self.toset.action(s=True), + 0x06, self.toset.action(), OP_STV, self.toset.action(s=True), self.toset.action() ]) +class VariableNew(): + def __init__(self, label, typed): + self.label = label + self.typed = typed + + def action(self): + return([ + OP_DEC, + self.label.action(s=True), + self.typed.action(), + self.label.action() + ]) + +class VariableAssignment(): + def __init__(self, label, expression): + self.label = label + self.expr = expression + + def action(self): + if self.label.is_property: + return(PropertyAssignment(self.label.obj, + self.label, + self.expr).action()) + else: + return([ + self.expr.action(), + OP_STV, + self.label.action(s=True), + self.label.action() + ]) + +class VariableGet(): + def __init__(self, label): + self.label = label + + def action(self): + if self.label.is_property: + return(PropertyGet(self.label.obj, self.label).action()) + else: + return([ + OP_LOV, + self.label.action(s=True), + self.label.action() + ]) + class FunctionDef(): def __init__(self, label, args, typed): self.label = label @@ -125,11 +140,16 @@ class FunctionCall(): self.arguements = arguements def action(self): - return([ - self.arguements.action(), - OP_CALL, - self.label.action() - ]) + if self.label.is_property: + return(MethodCall(self.label.obj, + self.label, + self.arguements).action()) + else: + return([ + self.arguements.action(), + OP_CALL, + self.label.action() + ]) #TODO: Implement this class ForLoop(): diff --git a/src/lc/interpreter.py b/src/lc/interpreter.py @@ -29,13 +29,15 @@ class Label(AbstractToken): if len(names) > 1: self.is_property = True - self.obj = names[0] + self.obj = Label(self.i, names[0]) self.data = names[1] + namespace = [self.i.objects[self.obj.data]] + else: + namespace = self.i.names self.scope = 0 self.expr = 0 - - for n, i in enumerate(self.i.names): + for n, i in enumerate(namespace): if self.data in i: self.expr = i.index(self.data) + 1 self.scope = 0 if n > 0 else 1 @@ -226,6 +228,8 @@ class Interpreter(): self.scopestack = [] self.names = [[]] + self.objects = {} + self.cur_obj_scope = "" self.scope = 0 self.cur_directives = [] @@ -244,6 +248,19 @@ class Interpreter(): return self.program[self.ln] return self.program[self.ln + n] + def ns_persist(self, index): + self.objects[self.line[1][index][0]] = [] + self.cur_obj_scope = self.line[1][index][0] + return False + + def ns_save(self): + self.objects[self.cur_obj_scope] = self.names[self.scope] + return False + + def ns_copy(self, key, index): + self.objects[self.line[1][key][0]] = self.objects[self.line[1][index][0]] + return False + def new_name(self, index): self.name_dec(self.line[1][index]) return False @@ -305,7 +322,7 @@ class Interpreter(): def op(self, opcode): return(Opcode(opcode)) - + def eval_label(self, index): return(Label(self, self.line[1][index])) diff --git a/src/lc/memonic.py b/src/lc/memonic.py @@ -1,6 +1,7 @@ OP_NULL = 0x00 OP_SYNC = 0x01 OP_PRINT = 0x02 +OP_DEBUG = 0x03 OP_ARGB = 0x0E OP_LIBC = 0x0F diff --git a/src/lc/parser.py b/src/lc/parser.py @@ -43,8 +43,8 @@ class Parser(): "_addr", "_type", "_plist", - "_sub", - "objbldr", + "func", + "class", "object", "int", "float", @@ -92,6 +92,15 @@ class Parser(): AtomicSymbol(":") ]) + self.statement_endebug = Statement( + "endebug", + expression=[ + AtomicSymbol("DEBUG"), + AtomicSymbol(";") + ], + init=(lambda x: [x.op(OP_DEBUG)]) + ) + self.statement_include = Statement( "include", expression=[ @@ -265,8 +274,8 @@ class Parser(): ]) ) - self.statement_pless_class = Statement( - "paramless_class", + self.statement_class = Statement( + "class", expression=[ AtomicSymbol("class"), self.label_def, @@ -275,37 +284,40 @@ class Parser(): ], init=(lambda x: [ x.new_name(1), + x.ns_persist(1), ClassDef(x.eval_label(1), - None), - x.add_directive(lambda x: [x.pop_scope(), + x.eval_param(2)), + x.add_directive(lambda x: [x.ns_save(), + x.pop_scope(), x.op(OP_ENDCLASS)]), x.push_scope() ]) ) - - self.statement_class = Statement( - "class", + self.statement_pless_class = Statement( + "paramless_class", expression=[ AtomicSymbol("class"), self.label_def, - self.paramlist_def, AtomicSymbol(":") ], init=(lambda x: [ x.new_name(1), + x.ns_persist(1), ClassDef(x.eval_label(1), - x.eval_param(2)), - x.add_directive(lambda x: [x.pop_scope(), + None), + x.add_directive(lambda x: [x.ns_save(), + x.pop_scope(), x.op(OP_ENDCLASS)]), x.push_scope() ]) ) + self.statement_new = Statement( "new", expression=[ - self.defined_types[6], + self.label_def, self.label_def, AtomicSymbol("="), AtomicSymbol("new"), @@ -315,6 +327,7 @@ class Parser(): ], init=(lambda x: [ x.new_name(1), + x.ns_copy(1, 0), NewClass(x.eval_label(1), x.eval_label(4), x.eval_args(5)) @@ -363,6 +376,7 @@ class Parser(): ) self.active_tokens = [ + self.statement_endebug, self.statement_include, self.statement_codeblock_begin, self.statement_codeblock_end, diff --git a/src/lc/test_files/class.ti b/src/lc/test_files/class.ti @@ -1,13 +1,42 @@ -class Wow(): + +class ObjectFibb: { - int cool = 32; + int a = 0; + int b = 1; + int c = 0; + + func next -> void: + { + if c == 0: + { + b = a + b; + c = 1; + } else + if c == 1: + { + a = a + b; + c = 0; + } + } + + func display -> void: + { + print b; + print a; + } - func test(int wow) -> void: + func run (int count) -> void: { - print cool * wow; + int x = 0; + while x < count: + { + next(); + display(); + x = x + 1; + } } } -object wee = new Wow(); +ObjectFibb test = new ObjectFibb(); -wee.test(3); +test.run(15); diff --git a/src/lc/test_files/fibb.ti b/src/lc/test_files/fibb.ti @@ -1,15 +0,0 @@ -func fibo(int limit) -> void: -{ - int a = 0; - int b = 1; - - while a < limit: - { - a = a + b; - print b; - b = a + b; - print a; - } -} - -fibo(1000); diff --git a/src/lc/test_files/if.ti b/src/lc/test_files/if.ti @@ -1,4 +0,0 @@ -include extern; -include test; - -print some_external_function(3); diff --git a/src/lc/test_files/test.ti b/src/lc/test_files/test.ti @@ -1,4 +1,4 @@ -include fibb; +include extern; func testing(int x, int y, int z) -> int: { @@ -6,4 +6,4 @@ func testing(int x, int y, int z) -> int: return rv; } -fibo(testing(2333, 3, 3)); +print some_external_function(testing(2333, 3, 3)); diff --git a/src/vm/inc/ins_def.h b/src/vm/inc/ins_def.h @@ -36,6 +36,7 @@ int ins_def_is_valid(bc_cont*); void _ins_def_NULL (rt_t*, bc_cont*); void _ins_def_SYNC (rt_t*, bc_cont*); void _ins_def_PRINT (rt_t*, bc_cont*); +void _ins_def_DEBUG (rt_t*, bc_cont*); void _ins_def_ARGB (rt_t*, bc_cont*); void _ins_def_LIBC (rt_t*, bc_cont*); diff --git a/src/vm/inc/ins_mdata.h b/src/vm/inc/ins_mdata.h @@ -25,6 +25,7 @@ /* NULL */ INS_MDATA[0x00] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* SYNC */ INS_MDATA[0x01] = encode(1, A_BYTE, A_BYTE, A_BYTE); \ /* PRINT */ INS_MDATA[0x02] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ +/* DEBUG */ INS_MDATA[0x03] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* ARGB */ INS_MDATA[0x0E] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* LIBC */ INS_MDATA[0x0F] = encode(1, A_ADDR, A_BYTE, A_BYTE); \ \ @@ -82,9 +83,10 @@ /* CALL */ INS_MDATA[0x7F] = encode(1, A_ADDR, A_BYTE, A_BYTE); \ \ /* GETN */ INS_MDATA[0x80] = encode(1, A_NAME, A_BYTE, A_BYTE); \ -/* CALLM */ INS_MDATA[0x81] = encode(1, A_NAME, A_BYTE, A_BYTE); \ -/* INDEXO */ INS_MDATA[0x82] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ -/* MODO */ INS_MDATA[0x83] = encode(1, A_BYTE, A_BYTE, A_BYTE); \ +/* SETN */ INS_MDATA[0x81] = encode(1, A_NAME, A_BYTE, A_BYTE); \ +/* CALLM */ INS_MDATA[0x82] = encode(1, A_NAME, A_BYTE, A_BYTE); \ +/* INDEXO */ INS_MDATA[0x83] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ +/* MODO */ INS_MDATA[0x84] = encode(1, A_BYTE, A_BYTE, A_BYTE); \ \ /* RETURN */ INS_MDATA[0xF0] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* NEW */ INS_MDATA[0xF1] = encode(1, A_NAME, A_BYTE, A_BYTE); \ @@ -104,7 +106,8 @@ #define INS_ADATA_DEF() \ /* NULL */ INS_ADATA[0x00] = encode(0, BTOI, BTOI, BTOI); \ /* SYNC */ INS_ADATA[0x01] = encode(1, BTOI, BTOI, BTOI); \ -/* PRINT */ INS_ADATA[0x01] = encode(0, BTOI, BTOI, BTOI); \ +/* PRINT */ INS_ADATA[0x02] = encode(0, BTOI, BTOI, BTOI); \ +/* DEBUG */ INS_ADATA[0x03] = encode(0, BTOI, BTOI, BTOI); \ /* ARGB */ INS_ADATA[0x0E] = encode(0, BTOI, BTOI, BTOI); \ /* LIBC */ INS_ADATA[0x0F] = encode(1, BTOI, BTOI, BTOI); \ \ @@ -162,9 +165,10 @@ /* CALL */ INS_ADATA[0x7F] = encode(1, BTOI, BTOI, BTOI); \ \ /* GETN */ INS_ADATA[0x80] = encode(1, BTOI, BTOI, BTOI); \ -/* CALLM */ INS_ADATA[0x81] = encode(1, BTOI, BTOI, BTOI); \ -/* INDEXO */ INS_ADATA[0x82] = encode(0, BTOI, BTOI, BTOI); \ -/* MODO */ INS_ADATA[0x83] = encode(1, BTOI, BTOI, BTOI); \ +/* SETN */ INS_ADATA[0x81] = encode(1, BTOI, BTOI, BTOI); \ +/* CALLM */ INS_ADATA[0x82] = encode(1, BTOI, BTOI, BTOI); \ +/* INDEXO */ INS_ADATA[0x83] = encode(0, BTOI, BTOI, BTOI); \ +/* MODO */ INS_ADATA[0x84] = encode(1, BTOI, BTOI, BTOI); \ \ /* RETURN */ INS_ADATA[0xF0] = encode(0, BTOI, BTOI, BTOI); \ /* NEW */ INS_ADATA[0xF1] = encode(1, BTOI, BTOI, BTOI); \ diff --git a/src/vm/inc/rt.h b/src/vm/inc/rt.h @@ -25,6 +25,7 @@ * [1] Function calls implement this stack to load variables as arguements. */ typedef struct rt_t { + int db; pc_t* pc; stk_t* stack; stk_t* argstk; diff --git a/src/vm/src/ins_def.c b/src/vm/src/ins_def.c @@ -21,6 +21,7 @@ void init_ins_def( void ) INS_DEF[0x00] = _ins_def_NULL; INS_DEF[0x01] = _ins_def_SYNC; INS_DEF[0x02] = _ins_def_PRINT; + INS_DEF[0x03] = _ins_def_DEBUG; INS_DEF[0x0E] = _ins_def_ARGB; INS_DEF[0x0F] = _ins_def_LIBC; @@ -105,6 +106,10 @@ void _ins_def_NULL (rt_t* ctx, bc_cont* line) { pc_inc(ctx->pc, 1); } +void _ins_def_SYNC (rt_t* ctx, bc_cont* line) +{ + pc_inc(ctx->pc, 1); +} void _ins_def_PRINT (rt_t* ctx, bc_cont* line) { var_cont* var = stk_pop(ctx->stack); @@ -113,8 +118,9 @@ void _ins_def_PRINT (rt_t* ctx, bc_cont* line) pc_inc(ctx->pc, 1); } -void _ins_def_SYNC (rt_t* ctx, bc_cont* line) +void _ins_def_DEBUG (rt_t* ctx, bc_cont* line) { + ctx->db = 0 ? ctx->db : 1; pc_inc(ctx->pc, 1); } void _ins_def_ARGB (rt_t* ctx, bc_cont* line) @@ -627,16 +633,18 @@ void _ins_def_CALLM (rt_t* ctx, bc_cont* line) ctx->vars = object->names; // Call the function _ins_def_function_call(ctx, func); + pc_update(ctx->pc); // Run code here so we can pop the namespace context int n; for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc)) { -#ifdef DEBUG - printf("[%i]:\t", ctx->pc->address); - bc_print_op(ctx->pc->line); - printf("\n"); -#endif // DEBUG + if (ctx->db) + { + printf("[%i]:\t", ctx->pc->address); + bc_print_op(ctx->pc->line); + printf("\n"); + } INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); @@ -653,8 +661,6 @@ void _ins_def_CALLM (rt_t* ctx, bc_cont* line) } // Pop the namespace context ctx->vars = ns_ctx_pop(ctx->varctx); - - pc_inc(ctx->pc, 1); } void _ins_def_INDEXO (rt_t* ctx, bc_cont* line) { diff --git a/src/vm/src/main.c b/src/vm/src/main.c @@ -6,6 +6,8 @@ #include "ins_def.h" #include "helper.h" +#define DEBUG 0 + int main(int argc, char** argv) { ASSERT(argc > 1, "Specify a bytecode file in the first and only argument, please\n"); diff --git a/src/vm/src/pc.c b/src/vm/src/pc.c @@ -83,7 +83,7 @@ void pc_addr_stk_del(pc_addr_stk* stk) void pc_update(pc_t* pc) { N_ASSERT(pc, "pc_update\n"); - ASSERT((pc->address <= pc->bc->size), "Uhoh\n"); + ASSERT((pc->address < (pc->bc->size + 1)), "Address out of range\n"); // Update the pointer pc->line = pc->bc->heap[pc->address]; } diff --git a/src/vm/src/proc.c b/src/vm/src/proc.c @@ -34,11 +34,12 @@ void proc_run(rt_t* ctx) for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc)) { -#ifdef DEBUG - printf("[%i]:\t", ctx->pc->address); - bc_print_op(ctx->pc->line); - printf("\n"); -#endif // DEBUG + if (ctx->db) + { + printf("[%i]:\t", ctx->pc->address); + bc_print_op(ctx->pc->line); + printf("\n"); + } INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); diff --git a/src/vm/src/var.c b/src/vm/src/var.c @@ -378,6 +378,11 @@ var_cont* var_data_cpy(var_cont* var) rv->data = var_data_cpy_G_STR(var->data); } + if (var->type == OBJECT) + { + rv->data = var->data; + } + ASSERT((rv->data != NULL), "ERROR: Could not copy type.\n"); return rv;