vua: Primitive function call support
authorJack Miller <jack@codezen.org>
Sat, 17 Sep 2016 21:03:06 +0000 (16:03 -0500)
committerJack Miller <jack@codezen.org>
Sat, 17 Sep 2016 21:03:06 +0000 (16:03 -0500)
Mostly untested, but can generate a call instruction.

vua/vua.c
vua/vua_bc.c
vua/vua_bc.h
vua/vua_parse.c

index 786f8ba..94488bc 100644 (file)
--- a/vua/vua.c
+++ b/vua/vua.c
@@ -9,7 +9,7 @@
 #include "vua_parse.h"
 #include "vua_test.h"
 
-char *test_prog = "function a() local a = 2; local x = 1; function b() y = 0; x = a; end end";
+char *test_prog = "function a() local a = 2; local x = 1; function b() y = 0; x = a; end end\na()";
 
 void vua_init(void)
 {
index b9be821..86f176c 100644 (file)
@@ -1061,3 +1061,32 @@ void vua_bc_fix_ret(parser_state_t *parser)
         }
     }
 }
+
+void vua_bc_emit_call(parser_state_t *parser, expr_t *f, expr_t *args)
+{
+    BCIns ins;
+    BCPos base = f->v.r.info;
+
+    /* Args = f(a, b, c()) or f (a, b, ...) */
+    if (args->type == VCALL) {
+
+        /* Final arg needs to be adjusted to be multiple return to set MULTRES
+         * correctly so args can be passed on to this call. Multi-return
+         * functions earlier in the arg list potentially have all but their
+         * first return overwritten by subsequent args.
+         */
+
+        setbc_b(bcptr(parser, args), 0);
+
+        ins = BCINS_ABC(BC_CALLM, base, 2, args->v.r.aux - base - 1);
+    } else {
+        if (args->type != VVOID)
+            vua_bc_tonextreg(parser, args);
+        ins = BCINS_ABC(BC_CALL, base, 2, parser->func->freereg - base);
+    }
+
+    f->type = VCALL;
+    f->v.r.info = __emit(parser, ins);
+    f->v.r.aux = base;
+    parser->func->freereg = base + 1;
+}
index d4b8c63..35227dc 100644 (file)
@@ -291,6 +291,7 @@ BCPos vua_bc_emit_proto(parser_state_t *parser, vua_proto_t *proto);
 BCPos vua_bc_emit_func(parser_state_t *parser);
 void vua_bc_emit_ret(parser_state_t *parser, int rets, expr_t *list);
 void vua_bc_emit_uclo(parser_state_t *parser, int nactvar);
+void vua_bc_emit_call(parser_state_t *parser, expr_t *f, expr_t *args);
 
 void vua_bc_fix_ret(parser_state_t *parser);
 
index aa2d17f..ef92cf6 100644 (file)
@@ -13,6 +13,7 @@ static DEFINE_OBJCACHE(parser_cache);
 
 static u32 __parse_expr_binop(parser_state_t *parser, expr_t *expr, u32 prio);
 static int __parse_block(parser_state_t *parser);
+static int __parse_expr_list(parser_state_t *parser, expr_t *expr);
 
 #define __parse_expr(p, e) __parse_expr_binop(p, e, 0)
 #define next()  vua_lexer_lex(&parser->lexer)
@@ -292,6 +293,23 @@ static void __remove_var(parser_state_t *parser, BCReg tolevel)
     }
 }
 
+static void __parse_args(parser_state_t *parser, expr_t *expr)
+{
+    expr_t args;
+
+    next();
+
+    if (parser->lexer.token == ')')
+        __expr_init(&args, VVOID);
+    else {
+        __parse_expr_list(parser, &args);
+    }
+
+    lex_check(')');
+
+    vua_bc_emit_call(parser, expr, &args);
+}
+
 /* Parse a standalone expression, like (), a function call or variable name,
  * these are allowed to be valid left hand sides for assignment
  */
@@ -311,6 +329,17 @@ static void __parse_expr_primary(parser_state_t *parser, expr_t *expr)
     }
 
     next();
+
+    while (1) {
+        token = parser->lexer.token;
+
+        if (token == '(') {
+            vua_bc_tonextreg(parser, expr);
+            __parse_args(parser, expr);
+        } else
+            break;
+
+    }
 }
 
 /* Parse a constant expression */
@@ -925,6 +954,9 @@ static int __parse_body(parser_state_t *parser, expr_t *expr, int needself)
             parent->flags |= PROTO_FIXUP_RETURN;
     }
 
+    /* Advance beyond whatever ended our body */
+    next();
+
     return 0;
 }