Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

for loops

  • Loading branch information...
commit e243fc2d605beaea88d947f248867c6fa4a7e507 1 parent e18c75c
@charliesome authored
View
8 inc/lex.h
@@ -59,6 +59,7 @@ typedef enum sl_token_type {
SL_TOK_PLUS,
SL_TOK_MINUS,
+ SL_TOK_POW,
SL_TOK_TIMES,
SL_TOK_DIVIDE,
SL_TOK_MOD,
@@ -71,6 +72,13 @@ typedef enum sl_token_type {
SL_TOK_AND,
SL_TOK_NOT,
+ SL_TOK_BIT_OR,
+ SL_TOK_BIT_AND,
+ SL_TOK_CARET,
+ SL_TOK_TILDE,
+
+ SL_TOK_RANGE_EX,
+ SL_TOK_RANGE,
SL_TOK_DOT,
SL_TOK_PAAMAYIM_NEKUDOTAYIM,
SL_TOK_END
View
3  inc/parse.h
@@ -60,6 +60,9 @@ sl_node_base_t*
sl_make_while_node(sl_node_base_t* expr, sl_node_base_t* body);
sl_node_base_t*
+sl_make_for_node(sl_node_base_t* lval, sl_node_base_t* expr, sl_node_base_t* body, sl_node_base_t* else_body);
+
+sl_node_base_t*
sl_make_class_node(sl_parse_state_t* ps, SLVAL name, sl_node_base_t* extends, sl_node_base_t* body);
sl_node_base_t*
View
1  inc/vm.h
@@ -35,6 +35,7 @@ typedef struct sl_lib {
SLVAL Bignum;
SLVAL Array;
+ SLVAL Array_Enumerator;
SLVAL Hash;
SLVAL Method;
View
181 src/eval.c
@@ -9,6 +9,7 @@
#include <gc.h>
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
sl_eval_ctx_t*
sl_make_eval_ctx(sl_vm_t* vm)
@@ -59,6 +60,119 @@ sl_do_file(sl_vm_t* vm, uint8_t* filename)
return ast->eval(ast, ctx);
}
+static void
+assign_var(sl_node_var_t* node, sl_eval_ctx_t* ctx, SLVAL val)
+{
+ sl_eval_ctx_t* octx = ctx;
+ while(ctx) {
+ if(st_lookup(ctx->vars, (st_data_t)node->name, NULL)) {
+ st_insert(ctx->vars, (st_data_t)node->name, (st_data_t)sl_get_ptr(val));
+ return;
+ }
+ ctx = ctx->parent;
+ }
+ st_insert(octx->vars, (st_data_t)node->name, (st_data_t)sl_get_ptr(val));
+}
+
+SLVAL
+sl_eval_assign_var(sl_node_assign_var_t* node, sl_eval_ctx_t* ctx)
+{
+ SLVAL val = node->rval->eval(node->rval, ctx);
+ assign_var(node->lval, ctx, val);
+ return val;
+}
+
+static void
+assign_ivar(sl_node_var_t* node, sl_eval_ctx_t* ctx, SLVAL val)
+{
+ sl_set_ivar(ctx->vm, ctx->self, node->name, val);
+}
+
+SLVAL
+sl_eval_assign_ivar(sl_node_assign_ivar_t* node, sl_eval_ctx_t* ctx)
+{
+ SLVAL val = node->rval->eval(node->rval, ctx);
+ assign_ivar(node->lval, ctx, val);
+ return val;
+}
+
+static void
+assign_cvar(sl_node_var_t* node, sl_eval_ctx_t* ctx, SLVAL val)
+{
+ sl_set_cvar(ctx->vm, ctx->self, node->name, val);
+}
+
+SLVAL
+sl_eval_assign_cvar(sl_node_assign_cvar_t* node, sl_eval_ctx_t* ctx)
+{
+ SLVAL val = node->rval->eval(node->rval, ctx);
+ assign_cvar(node->lval, ctx, val);
+ return val;
+}
+
+static void
+assign_const(sl_node_const_t* node, sl_eval_ctx_t* ctx, SLVAL val)
+{
+ SLVAL obj;
+ if(node->obj) {
+ obj = node->obj->eval(node->obj, ctx);
+ } else {
+ obj = ctx->self;
+ if(!sl_is_a(ctx->vm, obj, ctx->vm->lib.Class)) {
+ obj = sl_class_of(ctx->vm, obj);
+ }
+ }
+ sl_class_set_const2(ctx->vm, obj, node->id, val);
+}
+
+SLVAL
+sl_eval_assign_const(sl_node_assign_const_t* node, sl_eval_ctx_t* ctx)
+{
+ SLVAL val = node->rval->eval(node->rval, ctx);
+ assign_const(node->lval, ctx, val);
+ return val;
+}
+
+static void
+assign_send(sl_node_send_t* node, sl_eval_ctx_t* ctx, SLVAL val)
+{
+ sl_node_send_t n;
+ sl_node_immediate_t imm;
+ sl_node_base_t** args;
+ imm.base.eval = (sl_node_eval_fn_t)sl_eval_immediate;
+ imm.base.type = SL_NODE_IMMEDIATE;
+ imm.value = val;
+ memcpy(&n, node, sizeof(n));
+ n.id = sl_string_concat(ctx->vm, n.id, sl_make_cstring(ctx->vm, "="));
+ args = alloca(sizeof(sl_node_base_t*) * (n.arg_count + 1));
+ args[n.arg_count++] = &imm.base;
+ sl_eval_send(&n, ctx);
+}
+
+static void
+set_lval(sl_node_base_t* node, sl_eval_ctx_t* ctx, SLVAL val)
+{
+ switch(node->type) {
+ case SL_NODE_VAR:
+ assign_var((sl_node_var_t*)node, ctx, val);
+ break;
+ case SL_NODE_IVAR:
+ assign_ivar((sl_node_var_t*)node, ctx, val);
+ break;
+ case SL_NODE_CVAR:
+ assign_cvar((sl_node_var_t*)node, ctx, val);
+ break;
+ case SL_NODE_CONST:
+ assign_const((sl_node_const_t*)node, ctx, val);
+ break;
+ case SL_NODE_SEND:
+ assign_send((sl_node_send_t*)node, ctx, val);
+ break;
+ default:
+ sl_throw_message2(ctx->vm, ctx->vm->lib.TypeError, "Invalid lval in assignment");
+ }
+}
+
SLVAL
sl_eval_seq(sl_node_seq_t* node, sl_eval_ctx_t* ctx)
{
@@ -130,55 +244,6 @@ sl_eval_not(sl_node_unary_t* node, sl_eval_ctx_t* ctx)
}
SLVAL
-sl_eval_assign_var(sl_node_assign_var_t* node, sl_eval_ctx_t* ctx)
-{
- sl_eval_ctx_t* octx = ctx;
- SLVAL val = node->rval->eval(node->rval, ctx);
- while(ctx) {
- if(st_lookup(ctx->vars, (st_data_t)node->lval->name, NULL)) {
- st_insert(ctx->vars, (st_data_t)node->lval->name, (st_data_t)sl_get_ptr(val));
- return val;
- }
- ctx = ctx->parent;
- }
- st_insert(octx->vars, (st_data_t)node->lval->name, (st_data_t)sl_get_ptr(val));
- return val;
-}
-
-SLVAL
-sl_eval_assign_ivar(sl_node_assign_ivar_t* node, sl_eval_ctx_t* ctx)
-{
- SLVAL val = node->rval->eval(node->rval, ctx);
- sl_set_ivar(ctx->vm, ctx->self, node->lval->name, val);
- return val;
-}
-
-SLVAL
-sl_eval_assign_cvar(sl_node_assign_cvar_t* node, sl_eval_ctx_t* ctx)
-{
- SLVAL val = node->rval->eval(node->rval, ctx);
- sl_set_cvar(ctx->vm, ctx->self, node->lval->name, val);
- return val;
-}
-
-SLVAL
-sl_eval_assign_const(sl_node_assign_const_t* node, sl_eval_ctx_t* ctx)
-{
- SLVAL obj, val;
- if(node->lval->obj) {
- obj = node->lval->obj->eval(node->lval->obj, ctx);
- } else {
- obj = ctx->self;
- if(!sl_is_a(ctx->vm, obj, ctx->vm->lib.Class)) {
- obj = sl_class_of(ctx->vm, obj);
- }
- }
- val = node->rval->eval(node->rval, ctx);
- sl_class_set_const2(ctx->vm, obj, node->lval->id, val);
- return val;
-}
-
-SLVAL
sl_eval_immediate(sl_node_immediate_t* node, sl_eval_ctx_t* ctx)
{
(void)ctx;
@@ -263,7 +328,23 @@ sl_eval_if(sl_node_if_t* node, sl_eval_ctx_t* ctx)
}
SLVAL
-sl_eval_for(sl_node_for_t* node, sl_eval_ctx_t* ctx);
+sl_eval_for(sl_node_for_t* node, sl_eval_ctx_t* ctx)
+{
+ SLVAL enumerable = node->expr->eval(node->expr, ctx);
+ SLVAL enumerator = sl_send(ctx->vm, enumerable, "enumerate", 0, NULL);
+ SLVAL val;
+ int iterated = 0;
+ while(sl_is_truthy(sl_send(ctx->vm, enumerator, "next", 0, NULL))) {
+ val = sl_send(ctx->vm, enumerator, "current", 0, NULL);
+ set_lval(node->lval, ctx, val);
+ iterated = 1;
+ node->body->eval(node->body, ctx);
+ }
+ if(!iterated) {
+ node->else_body->eval(node->else_body, ctx);
+ }
+ return enumerable;
+}
SLVAL
sl_eval_while(sl_node_while_t* node, sl_eval_ctx_t* ctx)
View
7 src/lex.yy
@@ -113,14 +113,21 @@ HEX [0-9a-fA-F]
<SLASH>"+" { ADD_TOKEN(sl_make_token(SL_TOK_PLUS)); }
<SLASH>"-" { ADD_TOKEN(sl_make_token(SL_TOK_MINUS)); }
+<SLASH>"**" { ADD_TOKEN(sl_make_token(SL_TOK_POW)); }
<SLASH>"*" { ADD_TOKEN(sl_make_token(SL_TOK_TIMES)); }
<SLASH>"/" { ADD_TOKEN(sl_make_token(SL_TOK_DIVIDE)); }
<SLASH>"%" { ADD_TOKEN(sl_make_token(SL_TOK_MOD)); }
+<SLASH>"^" { ADD_TOKEN(sl_make_token(SL_TOK_CARET)); }
+<SLASH>"~" { ADD_TOKEN(sl_make_token(SL_TOK_TILDE)); }
+<SLASH>"&" { ADD_TOKEN(sl_make_token(SL_TOK_BIT_AND)); }
<SLASH>"&&" { ADD_TOKEN(sl_make_token(SL_TOK_AND)); }
+<SLASH>"|" { ADD_TOKEN(sl_make_token(SL_TOK_BIT_OR)); }
<SLASH>"||" { ADD_TOKEN(sl_make_token(SL_TOK_OR)); }
<SLASH>"!" { ADD_TOKEN(sl_make_token(SL_TOK_NOT)); }
+<SLASH>"..." { ADD_TOKEN(sl_make_token(SL_TOK_RANGE_EX)); }
+<SLASH>".." { ADD_TOKEN(sl_make_token(SL_TOK_RANGE)); }
<SLASH>"." { ADD_TOKEN(sl_make_token(SL_TOK_DOT)); }
<SLASH>"."{ID} { ADD_TOKEN(sl_make_token(SL_TOK_DOT)); ADD_TOKEN(sl_make_string_token(SL_TOK_IDENTIFIER, yytext + 1, yyleng - 1)); }
<SLASH>"::" { ADD_TOKEN(sl_make_token(SL_TOK_PAAMAYIM_NEKUDOTAYIM)); }
View
67 src/lib/array.c
@@ -11,6 +11,14 @@ typedef struct {
}
sl_array_t;
+typedef struct {
+ sl_object_t base;
+ SLVAL* items;
+ size_t count;
+ size_t at;
+}
+sl_array_enumerator_t;
+
static sl_object_t*
allocate_array(sl_vm_t* vm)
{
@@ -25,6 +33,12 @@ allocate_array(sl_vm_t* vm)
return (sl_object_t*)ary;
}
+static sl_object_t*
+allocate_array_enumerator()
+{
+ return GC_MALLOC(sizeof(sl_array_enumerator_t));
+}
+
static sl_array_t*
get_array(sl_vm_t* vm, SLVAL array)
{
@@ -86,12 +100,57 @@ sl_array_to_s(sl_vm_t* vm, SLVAL array)
return str;
}
+static SLVAL
+sl_array_enumerate(sl_vm_t* vm, SLVAL array)
+{
+ return sl_new(vm, vm->lib.Array_Enumerator, 1, &array);
+}
+
+static SLVAL
+sl_array_enumerator_init(sl_vm_t* vm, SLVAL self, SLVAL array)
+{
+ sl_array_enumerator_t* e = (sl_array_enumerator_t*)sl_get_ptr(self);
+ sl_array_t* a = get_array(vm, array);
+ e->items = a->items;
+ e->at = 0;
+ e->count = a->count;
+ return vm->lib.nil;
+}
+
+static SLVAL
+sl_array_enumerator_next(sl_vm_t* vm, SLVAL self)
+{
+ sl_array_enumerator_t* e = (sl_array_enumerator_t*)sl_get_ptr(self);
+ if(!e->items) {
+ sl_throw_message2(vm, vm->lib.Error, "Invalid operator on Array::Enumerator");
+ }
+ if(++e->at > e->count) {
+ return vm->lib._false;
+ } else {
+ return vm->lib._true;
+ }
+}
+
+static SLVAL
+sl_array_enumerator_current(sl_vm_t* vm, SLVAL self)
+{
+ sl_array_enumerator_t* e = (sl_array_enumerator_t*)sl_get_ptr(self);
+ if(!e->items) {
+ sl_throw_message2(vm, vm->lib.Error, "Invalid operator on Array::Enumerator");
+ }
+ if(e->at == 0 || e->at > e->count) {
+ sl_throw_message2(vm, vm->lib.Error, "Invalid operator on Array::Enumerator");
+ }
+ return e->items[e->at - 1];
+}
+
void
sl_init_array(sl_vm_t* vm)
{
vm->lib.Array = sl_define_class(vm, "Array", vm->lib.Object);
sl_class_set_allocator(vm, vm->lib.Array, allocate_array);
sl_define_method(vm, vm->lib.Array, "init", -1, sl_array_init);
+ sl_define_method(vm, vm->lib.Array, "enumerate", 0, sl_array_enumerate);
sl_define_method(vm, vm->lib.Array, "[]", 1, sl_array_get2);
sl_define_method(vm, vm->lib.Array, "[]=", 2, sl_array_set2);
sl_define_method(vm, vm->lib.Array, "length", 0, sl_array_length);
@@ -101,6 +160,14 @@ sl_init_array(sl_vm_t* vm)
sl_define_method(vm, vm->lib.Array, "shift", 0, sl_array_shift);
sl_define_method(vm, vm->lib.Array, "to_s", 0, sl_array_to_s);
sl_define_method(vm, vm->lib.Array, "inspect", 0, sl_array_to_s);
+
+ vm->lib.Array_Enumerator = sl_define_class3(
+ vm, sl_make_cstring(vm, "Enumerator"), vm->lib.Object, vm->lib.Array);
+
+ sl_class_set_allocator(vm, vm->lib.Array_Enumerator, allocate_array_enumerator);
+ sl_define_method(vm, vm->lib.Array_Enumerator, "init", 1, sl_array_enumerator_init);
+ sl_define_method(vm, vm->lib.Array_Enumerator, "next", 0, sl_array_enumerator_next);
+ sl_define_method(vm, vm->lib.Array_Enumerator, "current", 0, sl_array_enumerator_current);
}
SLVAL
View
88 src/parse.c
@@ -113,9 +113,20 @@ while_expression(sl_parse_state_t* ps)
static sl_node_base_t*
for_expression(sl_parse_state_t* ps)
{
- /* @TODO */
- (void)ps;
- return NULL;
+ sl_node_base_t *lval, *expr, *body, *else_body = NULL;
+ sl_token_t* tok;
+ expect_token(ps, SL_TOK_FOR);
+ /* @TODO allow other lvals */
+ tok = expect_token(ps, SL_TOK_IDENTIFIER);
+ lval = sl_make_var_node(ps, SL_NODE_VAR, sl_eval_var, tok->str);
+ expect_token(ps, SL_TOK_IN);
+ expr = expression(ps);
+ body = body_expression(ps);
+ if(peek_token(ps)->type == SL_TOK_ELSE) {
+ next_token(ps);
+ else_body = body_expression(ps);
+ }
+ return sl_make_for_node(lval, expr, body, else_body);
}
static sl_node_base_t*
@@ -357,15 +368,40 @@ call_expression(sl_parse_state_t* ps)
static sl_node_base_t*
power_expression(sl_parse_state_t* ps)
{
- /* @TODO */
- return call_expression(ps);
+ sl_node_base_t* left = call_expression(ps);
+ sl_node_base_t* right;
+ SLVAL id;
+ if(peek_token(ps)->type == SL_TOK_POW) {
+ id = next_token(ps)->str;
+ right = power_expression(ps);
+ left = sl_make_send_node(left, id, 1, &right);
+ }
+ return left;
}
static sl_node_base_t*
unary_expression(sl_parse_state_t* ps)
{
- /* @TODO */
- return power_expression(ps);
+ sl_node_base_t* expr;
+ SLVAL id;
+ switch(peek_token(ps)->type) {
+ case SL_TOK_MINUS:
+ next_token(ps);
+ id = sl_make_cstring(ps->vm, "negate");
+ expr = unary_expression(ps);
+ return sl_make_send_node(expr, id, 0, NULL);
+ case SL_TOK_TILDE:
+ next_token(ps);
+ id = sl_make_cstring(ps->vm, "~");
+ expr = unary_expression(ps);
+ return sl_make_send_node(expr, id, 0, NULL);
+ case SL_TOK_NOT:
+ next_token(ps);
+ expr = unary_expression(ps);
+ return sl_make_unary_node(expr, SL_NODE_NOT, sl_eval_not);
+ default:
+ return power_expression(ps);
+ }
}
static sl_node_base_t*
@@ -414,8 +450,22 @@ shift_expression(sl_parse_state_t* ps)
static sl_node_base_t*
bitwise_expression(sl_parse_state_t* ps)
{
- /* @TODO */
- return shift_expression(ps);
+ sl_node_base_t* left = shift_expression(ps);
+ sl_node_base_t* right;
+ SLVAL id;
+ while(1) {
+ switch(peek_token(ps)->type) {
+ case SL_TOK_BIT_OR:
+ case SL_TOK_BIT_AND:
+ case SL_TOK_CARET:
+ id = next_token(ps)->str;
+ right = shift_expression(ps);
+ left = sl_make_send_node(left, id, 1, &right);
+ break;
+ default:
+ return left;
+ }
+ }
}
static sl_node_base_t*
@@ -443,8 +493,24 @@ relational_expression(sl_parse_state_t* ps)
static sl_node_base_t*
logical_expression(sl_parse_state_t* ps)
{
- /* @TODO */
- return relational_expression(ps);
+ sl_node_base_t* left = relational_expression(ps);
+ sl_node_base_t* right;
+ while(1) {
+ switch(peek_token(ps)->type) {
+ case SL_TOK_OR:
+ next_token(ps);
+ right = relational_expression(ps);
+ left = sl_make_binary_node(left, right, SL_NODE_OR, sl_eval_or);
+ break;
+ case SL_TOK_AND:
+ next_token(ps);
+ right = relational_expression(ps);
+ left = sl_make_binary_node(left, right, SL_NODE_AND, sl_eval_and);
+ break;
+ default:
+ return left;
+ }
+ }
}
static sl_node_base_t*
View
11 src/parse_helper.c
@@ -139,6 +139,17 @@ sl_make_while_node(sl_node_base_t* expr, sl_node_base_t* body)
}
sl_node_base_t*
+sl_make_for_node(sl_node_base_t* lval, sl_node_base_t* expr, sl_node_base_t* body, sl_node_base_t* else_body)
+{
+ MAKE_NODE(SL_NODE_FOR, sl_eval_for, sl_node_for_t, {
+ node->lval = lval;
+ node->expr = expr;
+ node->body = body;
+ node->else_body = else_body;
+ });
+}
+
+sl_node_base_t*
sl_make_class_node(sl_parse_state_t* ps, SLVAL name, sl_node_base_t* extends, sl_node_base_t* body)
{
MAKE_NODE(SL_NODE_CLASS, sl_eval_class, sl_node_class_t, {
Please sign in to comment.
Something went wrong with that request. Please try again.