language

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

commit 8ad809648fed5219c2b6a5face7902f1efe9465c
parent 1a57060ad24708d470619d3b9d0c80b1cae96662
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Mon May  2 14:04:18 2016

More work on getting objects to work

Diffstat:
 doc/SPECIFICATION          | 13 ++++---
 src/lc/bytecode.py         | 48 +++++++++++++++++++++++----
 src/lc/interpreter.py      | 12 +++++++-
 src/lc/lexer.py            |  4 +-
 src/lc/main.py             |  5 ++-
 src/lc/memonic.py          |  7 ++--
 src/lc/parser.py           | 25 ++++++++++++--
 src/lc/test_files/class.ti | 11 +++---
 src/vm/Makefile            |  2 +-
 src/vm/inc/ins_def.h       |  5 ++-
 src/vm/inc/object.h        |  8 +++-
 src/vm/src/ins_def.c       | 85 +++++++++++++++++++++++++++++++++++++++++++++--
 src/vm/src/ns.c            |  4 +-
 src/vm/src/object.c        | 38 ++++++++++++++++++++-
 src/vm/src/proc.c          |  5 +--
 15 files changed, 237 insertions(+), 35 deletions(-)

diff --git a/doc/SPECIFICATION b/doc/SPECIFICATION @@ -283,11 +283,14 @@ to TOS ------------------------------------------------------------------------------- 80 GETN N<name> - Returns variable assosiated with name in object TBI -81 CALLM N<name> - Calls method in object TBI +81 SETN N<name> - Sets the variable assosiated with name in object TBI + Object on TOS, Variable on TOS1 -82 INDEXO - Index an object, uses arguement stack TBI +82 CALLM N<name> - Calls method in object TBI -83 MODO S<OP> - Modify an object based on op. [+, -, *, /, %, ^ .. etc] TBI +83 INDEXO - Index an object, uses arguement stack TBI + +84 MODO S<OP> - Modify an object based on op. [+, -, *, /, %, ^ .. etc] TBI ------------------------------------------------------------------------------- F - Functions/classes ------------------------------------------------------------------------------- @@ -295,11 +298,11 @@ FF DEFUN N<ref> S<type> D<args> - Un-funs everything. no, no- it defines a function. D<ref> is its name, S<type> is the return value, D<args> is the args. -FE DECLASS N<ref> D<args> - Defines a class. TBI +FE DECLASS N<ref> D<args> - Defines a class. F2 ENDCLASS - End of class block -F1 NEW N<ref> - Instantiates class TBI +F1 NEW N<ref> - Instantiates class F0 RETURN - Returns from function ------------------------------------------------------------------------------- diff --git a/src/lc/bytecode.py b/src/lc/bytecode.py @@ -20,21 +20,55 @@ class VariableAssignment(): 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.label = plabel + self.expr = expression + + def action(self): return([ self.expr.action(), - OP_STV, - self.label.action(s=True), + self.ovar.action(), + OP_SETN, self.label.action() ]) -class VariableGet(): - def __init__(self, label): - self.label = label +class PropertyGet(): + def __init__(self, ovar, plabel): + self.ovar = VariableGet(ovar) + self.label = plabel def action(self): return([ - OP_LOV, - self.label.action(s=True), + self.ovar.action(), + OP_GETN, self.label.action() ]) diff --git a/src/lc/interpreter.py b/src/lc/interpreter.py @@ -22,6 +22,15 @@ class Label(AbstractToken): def update(self): f = lambda y, x: y(y, x[0]) if type(x) is list else x self.data = f(f, self.data) + self.is_property = False + self.obj = None + + names = self.data.rsplit(".", 1) + + if len(names) > 1: + self.is_property = True + self.obj = names[0] + self.data = names[1] self.scope = 0 self.expr = 0 @@ -32,6 +41,9 @@ class Label(AbstractToken): self.scope = 0 if n > 0 else 1 break + if self.expr == 0: + print("UNDEFINED REFERENCE TO VARIABLE '{}'".format(self.data)) + def action(self, s=False): if s: return(self.scope) diff --git a/src/lc/lexer.py b/src/lc/lexer.py @@ -77,6 +77,7 @@ class PolySymbol(): class GroupingSymbol(PolySymbol): def match(self, tokenstring, index): + found = False rv = [] r = self.symbols[0].match(tokenstring, index) if r[0]: @@ -97,12 +98,13 @@ class GroupingSymbol(PolySymbol): index = r[0] else: index = r[0] + found = True break else: rv.append(tokenstring[index]) index += 1 - return [index, rv] if len(rv) > 0 else [False, None] + return [index, rv] if found else [False, None] class Statement(): def __init__(self, name, expression=[], init=None): diff --git a/src/lc/main.py b/src/lc/main.py @@ -36,7 +36,10 @@ if __name__ == "__main__": print("\nTO BYTES\n") rv = [] for n, l in enumerate(itr.program): - print("{}: {} <= ".format(str(n).rjust(4),l[0].name.rjust(15), l[1]), end="") + print("{}: {} <= ".format(str(n).rjust(4), + l[0].name.rjust(15), + l[1]), + end="") for e in l[2]: t = e.action() printb(t) diff --git a/src/lc/memonic.py b/src/lc/memonic.py @@ -58,9 +58,10 @@ OP_DONE = 0x7E OP_CALL = 0x7F OP_GETN = 0x80 -OP_CALLM = 0x81 -OP_INDEXO = 0x82 -OP_MODO = 0x83 +OP_SETN = 0x81 +OP_CALLM = 0x82 +OP_INDEXO = 0x83 +OP_MODO = 0x84 OP_RETURN = 0xF0 OP_NEW = 0xF1 diff --git a/src/lc/parser.py b/src/lc/parser.py @@ -64,7 +64,7 @@ class Parser(): [self.int_def] + [self.str_def] + self.known_tokens ) - + self.paramlist_def = GroupingSymbol( [ AtomicSymbol("\("), AtomicSymbol("\)") @@ -265,6 +265,25 @@ class Parser(): ]) ) + self.statement_pless_class = Statement( + "paramless_class", + expression=[ + AtomicSymbol("class"), + self.label_def, + self.paramlist_def, + AtomicSymbol(":") + ], + init=(lambda x: [ + x.new_name(1), + ClassDef(x.eval_label(1), + None), + x.add_directive(lambda x: [x.pop_scope(), + x.op(OP_ENDCLASS)]), + x.push_scope() + ]) + ) + + self.statement_class = Statement( "class", expression=[ @@ -356,6 +375,7 @@ class Parser(): self.statement_while, self.statement_func, self.statement_proc, + self.statement_pless_class, self.statement_class, self.statement_new, self.statement_inst, @@ -384,7 +404,8 @@ class Parser(): rv.extend(l) else: rv.append([a,r,[]]) - print("{}: {}\t{}".format(str(num).rjust(4), a.name.rjust(15),r)) + print("{}: {}\t{}".format(str(num).rjust(4), + a.name.rjust(15),r)) break return rv diff --git a/src/lc/test_files/class.ti b/src/lc/test_files/class.ti @@ -1,12 +1,13 @@ - -class Wow(int cool): +class Wow(): { + int cool = 32; + func test(int wow) -> void: { print cool * wow; } - - test(4); } -object wee = new Wow(3); +object wee = new Wow(); + +wee.test(3); diff --git a/src/vm/Makefile b/src/vm/Makefile @@ -47,4 +47,4 @@ clean: rm $(OUT) install: - mv $(OUT) $(DST_DIR) + cp $(OUT) $(DST_DIR) diff --git a/src/vm/inc/ins_def.h b/src/vm/inc/ins_def.h @@ -97,8 +97,11 @@ void _ins_def_IFDO (rt_t*, bc_cont*); void _ins_def_ELSE (rt_t*, bc_cont*); void _ins_def_DONE (rt_t*, bc_cont*); void _ins_def_CALL (rt_t*, bc_cont*); - +/* HELPER FUNCTIONS */ +void _ins_def_function_call(rt_t*, var_data_func*); +/* END HELPER FUNCTIONS */ void _ins_def_GETN (rt_t*, bc_cont*); +void _ins_def_SETN (rt_t*, bc_cont*); void _ins_def_CALLM (rt_t*, bc_cont*); void _ins_def_INDEXO (rt_t*, bc_cont*); void _ins_def_MODO (rt_t*, bc_cont*); diff --git a/src/vm/inc/object.h b/src/vm/inc/object.h @@ -7,12 +7,12 @@ #include <stdlib.h> #include "ns.h" +#include "var.h" #include "helper.h" typedef struct obj_t { ns_t* names; - ns_addr mod_ops[0x100]; } obj_t; /* Initalize an empty object of size @@ -23,4 +23,10 @@ obj_t* object_init(); */ void object_del(void*); +var_cont* object_get_name(obj_t*, ns_addr); + +void object_set_name(obj_t*, ns_addr, var_cont*); + +var_cont* object_call_method(obj_t*, ns_addr); + #endif // OBJECT_H diff --git a/src/vm/src/ins_def.c b/src/vm/src/ins_def.c @@ -78,9 +78,10 @@ void init_ins_def( void ) INS_DEF[0x7F] = _ins_def_CALL; INS_DEF[0x80] = _ins_def_GETN; - INS_DEF[0x81] = _ins_def_CALLM; - INS_DEF[0x82] = _ins_def_INDEXO; - INS_DEF[0x83] = _ins_def_MODO; + INS_DEF[0x81] = _ins_def_SETN; + INS_DEF[0x82] = _ins_def_CALLM; + INS_DEF[0x83] = _ins_def_INDEXO; + INS_DEF[0x84] = _ins_def_MODO; INS_DEF[0xF0] = _ins_def_RETURN; INS_DEF[0xF1] = _ins_def_NEW; @@ -541,6 +542,12 @@ void _ins_def_CALL (rt_t* ctx, bc_cont* line) var_cont* var = proc_getvar(ctx, 1, name); var_data_func* func = var_data_get_FUNC(var); + // Call the function + _ins_def_function_call(ctx, func); +} + +void _ins_def_function_call(rt_t* ctx, var_data_func* func) +{ // Push a new namespace of specified size ns_push(ctx->vars, func->size); // Declare the return value @@ -572,10 +579,81 @@ void _ins_def_CALL (rt_t* ctx, bc_cont* line) void _ins_def_GETN (rt_t* ctx, bc_cont* line) { + int name = var_data_get_G_INT(line->varg[0]); + + var_cont* obj = stk_pop(ctx->stack); + + var_data_object* obj_var_data = var_data_get_OBJECT(obj); + + obj_t* object = (obj_t*)obj_var_data->ref; + + var_cont* var = object_get_name(object, name); + + stk_push(ctx->stack, var); + + pc_inc(ctx->pc, 1); +} +void _ins_def_SETN (rt_t* ctx, bc_cont* line) +{ + int name = var_data_get_G_INT(line->varg[0]); + + var_cont* obj = stk_pop(ctx->stack); + + var_cont* var = stk_pop(ctx->stack); + + var_data_object* obj_var_data = var_data_get_OBJECT(obj); + + obj_t* object = (obj_t*)obj_var_data->ref; + + object_set_name(object, name, var); + pc_inc(ctx->pc, 1); } void _ins_def_CALLM (rt_t* ctx, bc_cont* line) { + int name = var_data_get_G_INT(line->varg[0]); + // Pop the stack to get the object + var_cont* obj = stk_pop(ctx->stack); + // Get the objects variable data + var_data_object* obj_var_data = var_data_get_OBJECT(obj); + // Cast reference to object type + obj_t* object = (obj_t*)obj_var_data->ref; + // Get the method to call + var_cont* var = object_get_name(object, name); + var_data_func* func = var_data_get_FUNC(var); + // Push current namespace context + ns_ctx_push(ctx->varctx, ctx->vars); + // Set current namespace to objects namespace + ctx->vars = object->names; + // Call the function + _ins_def_function_call(ctx, func); + + // 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 + + INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); + + // Break when the function returns + if (ctx->pc->line->op == 0x7F) + n++; + else if (ctx->pc->line->op == 0xF0) + { + if (n > 0) + n--; + else + break; + } + } + // 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) @@ -662,6 +740,7 @@ void _ins_def_ENDCLASS (rt_t* ctx, bc_cont* line) stk_push(ctx->stack, new); pc_return(ctx->pc); + pc_inc(ctx->pc, 1); } void _ins_def_DECLASS (rt_t* ctx, bc_cont* line) { diff --git a/src/vm/src/ns.c b/src/vm/src/ns.c @@ -44,9 +44,9 @@ void ns_ctx_push(ns_ctx* ctx, ns_t* ns) */ ns_t* ns_ctx_pop(ns_ctx* ctx) { - N_ASSERT(ctx, "ns_ctx_push\n"); + N_ASSERT(ctx, "ns_ctx_pop\n"); - ASSERT((ctx->ptr - 1) >= NS_CTX_DEPTH, "ns_ctx overflow"); + ASSERT((ctx->ptr - 1) >= 0, "ns_ctx underflow"); ctx->ptr = ctx->ptr - 1; return ctx->spaces[ctx->ptr]; diff --git a/src/vm/src/object.c b/src/vm/src/object.c @@ -3,6 +3,7 @@ #include "object.h" #include "ns.h" +#include "var.h" #include "helper.h" @@ -11,7 +12,7 @@ obj_t* object_init() obj_t* rv = (obj_t*)malloc(sizeof(obj_t)); M_ASSERT(rv); - rv->names = NULL; + rv->names = NULL; return rv; } @@ -27,3 +28,38 @@ void object_del(void* object) free(o); } + +obj_t* object_get(void* object) +{ + N_ASSERT(object, "object_get\n"); + + obj_t* o = object; + + return o; +} + +var_cont* object_get_name(obj_t* object, ns_addr name) +{ + N_ASSERT(object, "object_get_name\n"); + + var_cont* value = ns_get(object->names, 1, name); + + return value; +} + +void object_set_name(obj_t* object, ns_addr name, var_cont* var) +{ + N_ASSERT(object, "object_set_name\n"); + N_ASSERT(var, "object_set_name\n"); + + ns_set(object->names, 1, name, var); +} + +var_cont* object_call_method(obj_t* object, ns_addr name) +{ + N_ASSERT(object, "object_call_method\n"); + + var_cont* rv = NULL; + + return rv; +} 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 + INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); n++;