compile_expr(cm, expr->call.func);
EMIT(BC_CALL);
break;
+ case IR_E_SEND:
+ compile_list(cm, expr->send.message);
+ compile_expr(cm, expr->send.target);
+ EMIT(BC_SEND);
+ break;
case IR_E_VAR:
if (expr->var->is_upvalue) {
EMIT(BC_LD_UPVAL);
});
}
+static sbIrExpr *expr_send(hIrChunk ck, sbIrExpr *target, sbIrExpr *message) {
+ return new_expr(ck, &(sbIrExpr) {
+ .type = IR_E_SEND,
+ .send.target = target,
+ .send.message = message,
+ });
+}
+
static sbIrExpr *expr_list(hIrChunk ck, sbIrExpr *value) {
return new_expr(ck, &(sbIrExpr) {
.type = IR_E_LIST,
sbIrExpr *called = compile_ast_expr(ck, node->seq.left, FALSE);
sbIrExpr *params = compile_ast_list(ck, node->seq.right);
return expr_call(ck, called, params);
+ } else if (node->type == AST_NODE_METHODCALL) {
+ sbIrExpr *target = compile_ast_expr(ck, node->seq.left, FALSE);
+ sbIrExpr *message = compile_ast_list(ck, node->seq.right);
+ return expr_send(ck, target, message);
} else if (node->type == AST_VAL_FUNC) {
sbIrChunk *func = compile_ast_function(ck->program, node->seq.left, node->seq.right);
return expr_func(ck, func);
IR_E_VAR,
IR_E_FUNC,
IR_E_CALL,
+ IR_E_SEND,
IR_E_LIST,
IR_E_HASH,
} sbIrExprType;
struct sbIrExpr *this;
struct sbIrExpr *next;
} list;
+ struct {
+ struct sbIrExpr *target;
+ struct sbIrExpr *message;
+ } send;
};
} sbIrExpr;
case IR_E_CALL:
debug("CALL: ");
print_expr(e->call.func);
- debug(" with params ");
- sbIrExpr *param = e->call.param;
- while (param) {
- print_expr(param->list.this);
- debug(",");
- param = param->list.next;
- }
+ debug(" with params (");
+ print_expr(e->call.param);
+ debug(")");
+ break;
+ case IR_E_SEND:
+ debug("SEND: ");
+ print_expr(e->send.target);
+ debug(" <~( ");
+ print_expr(e->send.message);
+ debug(" )");
break;
case IR_E_LIST:
print_expr(e->list.this);
--- /dev/null
+#include "data/methods.h"
+
+#include "vm/exec.h"
+#include "data/symbol.h"
+#include "data/list.h"
+
+#define METHOD_IS(name) (!sbstrncmp(method_name, name, sizeof(name)))
+
+void sbList_method(hV list, hVm vm) {
+ if (list.type != IT_LIST) {
+ CHECK("can't call sbList_method on something that isn't a list");
+ }
+ hV argc = sbVm_pop(vm);
+ if (argc.type != IT_INTEGER) {
+ CHECK("argc of send should be integer!");
+ }
+ /* subtract 1 because the method name is itself a param */
+ usize num_params = argc.integer - 1;
+ hV *method_name_val = sbVm_peek(vm, num_params);
+ if (method_name_val->type == IT_SYMBOL) {
+ const char *method_name = sbSymbol_name(method_name_val->symbol);
+ printf("method name: %s\n", method_name);
+ if (METHOD_IS("each")) {
+ if (num_params != 1) {
+ PANIC("wrong number of arguments passed to list#each!");
+ }
+ hV loop_func = sbVm_pop(vm);
+ sbVm_pop(vm); /* remove method name */
+ usize length;
+ hV *iter_values = sbList_get_value(list.list, &length);
+ for (usize i = 0; i < length; i++) {
+ /* TODO : This doesn't work! It almost works, but when we call the
+ * callback func, we need to, like, pause this function and run more
+ * VM instructions, then come back to this one. How do? :thinking emoji: */
+ printf("index %zu\n", i);
+ sbVm_push(vm, iter_values[i]);
+ sbVm_push(vm, HVINT(1));
+ printf("call loop-func\n");
+ sbVm_call_func(vm, loop_func);
+ /* remove result of loop_func */
+ printf("loop-func done\n");
+ sbVm_pop(vm);
+ }
+ }
+ } else {
+ PANIC("method name to list is not symbol! (%lld)", method_name_val->type);
+ }
+}
+
--- /dev/null
+#include "common.h"
+
+void sbList_method(hV list, hVm vm);
#include "common.h"
+#define FLAG_SQUIGGLY (1ULL << 62)
+
#define HVINT(n) ((hV) { .type = IT_INTEGER, .integer = n })
#define HVSTR(s) ((hV) { .type = IT_STRING, .string = s })
#define HVSYM(s) ((hV) { .type = IT_SYMBOL, .symbol = s })
#define HVNIL ((hV) { .type = IT_NIL })
#define HVNOTHING ((hV) {0})
#define HVFUNC(i, c) ((hV) { .type = i, .closure = c })
+#define HVFUNC2(i, c) ((hV) { .type = i | FLAG_SQUIGGLY, .closure = c })
typedef u64 hHash;
typedef u64 hString;
method_name = parse_name_as_sym(pr);
}
if (method_name == NO_NODE) return syntax_error(pr);
- if (!expect(pr, T_LPAREN)) return syntax_error(pr);
- sbAst params = parse_comma_exprs(pr, NULL);
- if (!expect(pr, T_RPAREN)) return syntax_error(pr);
+ sbAst params = NO_NODE;
+ if (expect(pr, T_LPAREN)) {
+ params = parse_comma_exprs(pr, NULL);
+ if (!expect(pr, T_RPAREN)) return syntax_error(pr);
+ }
ast_type = AST_NODE_METHODCALL;
if (op.type == T_ARROW) {
/* (whatever)->x is rewritten as (*whatever).x */
lhs = unop_node(pr, AST_OP_DEREF, lhs);
}
- rhs = seq_node(pr, AST_NODE_NEXT, method_name, params);
+ rhs = seq_node(pr, AST_NODE_MULTIVAL, method_name, params);
} else if (op.type == T_BACKSQUIGARROW) {
/* a <~ b, c, d can have multiple comma things on the right side */
if (!expect(pr, T_LPAREN)) return syntax_error(pr);
void call_block(hVm vm, usize block_id, hClosure closure);
void execute_instruction(hVm vm);
+void push_stack(hVm vm, const hV *value);
+hV pop_stack(hVm vm);
+hV *npop_stack(hVm vm, usize count);
+hV *peek_stack(hVm vm, usize offset);
void sbVm_initialize(hVm vm, usize stacksize, usize rstacksize, flag debugmode) {
*vm = (sbVm) {0};
return VM_STAT_SUCCESS;
}
+void sbVm_push(hVm vm, hV value) {
+ push_stack(vm, &value);
+}
+
+hV sbVm_pop(hVm vm) {
+ return pop_stack(vm);
+}
+
+hV *sbVm_peek(hVm vm, usize where) {
+ return peek_stack(vm, where);
+}
+
+void sbVm_call_func(hVm vm, hV func) {
+ call_block(vm, func.type, func.closure);
+}
+
/* --- */
void call_block(hVm vm, usize block_id, hClosure closure) {
}
call_block(vm, vv.type, vv.closure);
break;
+ case BC_SEND:
+ sbV_message_handler(vm);
+ break;
case BC_NUMARG:
param = get_param(vm);
vv = pop_stack(vm);
case BC_RET:
return_from_block(vm);
break;
- case BC_SEND:
- PANIC("todo");
case BC_OP_EQ:
v = peek_stack(vm, 1);
w = peek_stack(vm, 0);
flag debugmode;
} sbVm;
-typedef sbVm *hVm;
-
void sbVm_initialize(hVm vm, usize stacksize, usize rstacksize, flag debugmode);
void sbVm_deinitialize(hVm vm);
sbVmStatus sbVm_execute(hVm vm, sbVmProgram *pm);
+
+void sbVm_push(hVm vm, hV value);
+
+hV sbVm_pop(hVm vm);
+
+hV *sbVm_peek(hVm vm, usize where);
+
+void sbVm_call_func(hVm vm, hV func);
#include "vm/operations.h"
+#include "vm/exec.h"
#include "data/integer.h"
#include "data/list.h"
#include "data/hashtable.h"
+#include "data/methods.h"
+
+void sbV_message_handler(hVm vm) {
+ hV target = sbVm_pop(vm);
+ switch(target.type) {
+ case IT_LIST:
+ sbList_method(target, vm);
+ break;
+ default:
+ if (target.type < 0) {
+ PANIC("haven't implemented method calling for this intrinsic type!");
+ }
+ if (target.type & FLAG_SQUIGGLY) {
+ /* squiggle function */
+ sbVm_call_func(vm, target);
+ } else {
+ /* normal function */
+ PANIC("haven't implemented method calling for functions yet!");
+ //sbFunction_method(target, vm);
+ }
+ }
+}
hV sbV_add(const hV *a, const hV *b) {
if (a->type == IT_INTEGER && b->type == IT_INTEGER) {
#include "common.h"
+void sbV_message_handler(hVm vm);
+
hV sbV_add(const hV *a, const hV *b);
hV sbV_sub(const hV *a, const hV *b);
#define __SARABANDE_VM_H__
#include "vm/bytecode.h"
+#include "data/value.h"
+
+struct sbVm;
+typedef struct sbVm *hVm;
#endif