Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implement Hash.

  • Loading branch information...
commit e723c70f37e685a28f5bd233d38cfc8fd0d5d0cb 1 parent 7df03aa
@macournoyer authored
View
3  TODO
@@ -16,7 +16,8 @@
[x] Bootstrap all class correctly (nil,true,false too)
[x] Fix CallSite error in recursive calls
[x] Allow reopening classes
-[ ] Implement Array, Hash
+[x] Implement Array
+[x] Implement Hash
[ ] Implement Module
[ ] Implement Proc, yield and all that Jazz
[ ] Implement some more corelib stuff in Ruby and embed bytecode
View
11 test/hash.rb
@@ -0,0 +1,11 @@
+h = { :a => 1, :b => 2 }
+
+puts h[:a]
+# => 1
+
+puts h[:c]
+# =>
+
+h.delete(:a)
+puts h[:a]
+# =>
View
12 vm/compiler.c
@@ -128,6 +128,7 @@ TrCompiler *TrCompiler_new(VM, const char *fn) {
void TrCompiler_compile_node(VM, TrCompiler *c, TrBlock *b, TrNode *n, int reg) {
assert(n && "nil node");
if (reg >= b->regc) b->regc++;
+ /* TODO this shit is very repetitive, need to refactor */
switch (n->ntype) {
case AST_ROOT:
case AST_BLOCK:
@@ -154,6 +155,17 @@ void TrCompiler_compile_node(VM, TrCompiler *c, TrBlock *b, TrNode *n, int reg)
}
PUSH_OP_AB(b, NEWARRAY, reg, size);
} break;
+ case AST_HASH: {
+ size_t size = 0;
+ if (n->args[0]) {
+ size = TR_ARRAY_SIZE(n->args[0]);
+ /* compile args */
+ TR_ARRAY_EACH(n->args[0], i, v, {
+ TrCompiler_compile_node(vm, c, b, (TrNode *)v, reg+i+1);
+ });
+ }
+ PUSH_OP_AB(b, NEWHASH, reg, size/2);
+ } break;
case AST_ASSIGN: {
int i = TrBlock_local(c->block, n->args[0]);
TrCompiler_compile_node(vm, c, b, (TrNode *)n->args[1], reg);
View
5 vm/grammar.y
@@ -58,6 +58,8 @@ literal(A) ::= RETURN. { A = NODE(RETURN, 0); }
literal(A) ::= CONST(B). { A = NODE(CONST, B); }
literal(A) ::= O_SBRA C_SBRA. { A = NODE(ARRAY, 0); }
literal(A) ::= O_SBRA args(B) C_SBRA. { A = NODE(ARRAY, B); }
+literal(A) ::= O_CBRA C_CBRA. { A = NODE(HASH, 0); }
+literal(A) ::= O_CBRA hash_items(B) C_CBRA. { A = NODE(HASH, B); }
assign_out(A) ::= CONST(B) ASSIGN statement(C). { A = NODE2(SETCONST, B, C); }
assign_out(A) ::= ID(B) ASSIGN statement(C). { A = NODE2(ASSIGN, B, C); }
@@ -97,6 +99,9 @@ args(A) ::= arg(B). { A = NODES(B); }
arg(A) ::= expr(B). { A = B; }
arg(A) ::= assign(B). { A = B; }
+hash_items(A) ::= hash_items(B) COMMA expr(C) HASHI expr(D). { A = PUSH(B, C); A = PUSH(B, D); }
+hash_items(A) ::= expr(B) HASHI expr(C). { A = NODES_N(2, B, C); }
+
def(A) ::= DEF ID(B) TERM statements(D) opt_term END. { A = NODE3(DEF, B, 0, D); }
def(A) ::= DEF ID(B) O_PAR params(C) C_PAR TERM statements(D) opt_term END. { A = NODE3(DEF, B, C, D); }
View
59 vm/hash.c
@@ -1,2 +1,61 @@
#include "tr.h"
#include "internal.h"
+
+OBJ TrHash_new(VM) {
+ TrHash *h = TR_INIT_OBJ(Hash);
+ h->kh = kh_init(OBJ);
+ return (OBJ)h;
+}
+
+OBJ TrHash_new2(VM, size_t n, OBJ items[]) {
+ TrHash *h = (TrHash *)TrHash_new(vm);
+ size_t i;
+ int ret;
+ for (i = 0; i < n; i+=2) {
+ khiter_t k = kh_put(OBJ, h->kh, items[i], &ret);
+ kh_value(h->kh, k) = items[i+1];
+ }
+ return (OBJ)h;
+}
+
+static OBJ TrHash_size(VM, OBJ self) {
+ TrHash *h = TR_CHASH(self);
+ return TrFixnum_new(vm, kh_size(h->kh));
+}
+
+/* TODO use Object#hash as the key */
+static OBJ TrHash_get(VM, OBJ self, OBJ key) {
+ TrHash *h = TR_CHASH(self);
+ khiter_t k = kh_get(OBJ, h->kh, key);
+ if (k != kh_end(h->kh)) return kh_value(h->kh, k);
+ return TR_NIL;
+}
+
+static OBJ TrHash_set(VM, OBJ self, OBJ key, OBJ value) {
+ TrHash *h = TR_CHASH(self);
+ int ret;
+ khiter_t k = kh_put(OBJ, h->kh, key, &ret);
+ if (!ret) kh_del(OBJ, h->kh, k);
+ kh_value(h->kh, k) = value;
+ return value;
+}
+
+static OBJ TrHash_delete(VM, OBJ self, OBJ key) {
+ TrHash *h = TR_CHASH(self);
+ khiter_t k = kh_get(OBJ, h->kh, key);
+ if (k != kh_end(h->kh)) {
+ OBJ value = kh_value(h->kh, k);
+ kh_del(OBJ, h->kh, k);
+ return value;
+ }
+ return TR_NIL;
+}
+
+void TrHash_init(VM) {
+ OBJ c = TR_INIT_CLASS(Hash, Object);
+ tr_def(c, "length", TrHash_size, 0);
+ tr_def(c, "size", TrHash_size, 0);
+ tr_def(c, "[]", TrHash_get, 1);
+ tr_def(c, "[]=", TrHash_set, 2);
+ tr_def(c, "delete", TrHash_delete, 1);
+}
View
6 vm/internal.h
@@ -13,7 +13,8 @@
#define NODE(T,A) TrNode_new(compiler->vm, AST_##T, (A), 0, 0)
#define NODE2(T,A,B) TrNode_new(compiler->vm, AST_##T, (A), (B), 0)
#define NODE3(T,A,B,C) TrNode_new(compiler->vm, AST_##T, (A), (B), (C))
-#define NODES(N) TrArray_new2(compiler->vm, 1, (N))
+#define NODES(I) TrArray_new2(compiler->vm, 1, (I))
+#define NODES_N(N,I...) TrArray_new2(compiler->vm, (N), ##I)
#define PUSH(A,N) (({ TR_ARRAY_PUSH((A), (N)); }), A)
typedef enum {
@@ -37,7 +38,8 @@ typedef enum {
AST_CLASS,
AST_CONST,
AST_SETCONST,
- AST_ARRAY
+ AST_ARRAY,
+ AST_HASH
} TrNodeType;
typedef struct {
View
7 vm/opcode.h
@@ -35,6 +35,7 @@ enum TrInstCode {
TR_OP_SETCONST, /* A Bx Consts[k[Bx]] = R[A] */
TR_OP_CLASS, /* A Bx R[A] = define class k[Bx] on self w/ blocks[A] */
TR_OP_NEWARRAY, /* A B R[A] = Array.new(R[A+1]..R[A+1+B]) */
+ TR_OP_NEWHASH, /* A B R[A] = Hash.new(R[A+1] => R[A+2] .. R[A+1+B*2] => R[A+2+B*2]) */
TR_OP_UNDEF,
TR_OP_ALIAS,
TR_OP_SUPER,
@@ -47,7 +48,6 @@ enum TrInstCode {
TR_OP_SETCVAR,
TR_OP_GETGLOBAL,
TR_OP_SETGLOBAL,
- TR_OP_NEWHASH,
TR_OP_NEWRANGE
};
@@ -76,6 +76,7 @@ enum TrInstCode {
"setconst", \
"class", \
"newarray", \
+ "newhash", \
"undef", \
"alias", \
"super", \
@@ -88,7 +89,6 @@ enum TrInstCode {
"setcvar", \
"getglobal", \
"setglobal", \
- "newhash", \
"newrange"
@@ -118,7 +118,8 @@ enum TrInstCode {
&&op_GETCONST, \
&&op_SETCONST, \
&&op_CLASS, \
- &&op_NEWARRAY
+ &&op_NEWARRAY, \
+ &&op_NEWHASH
#endif
View
3  vm/scanner.rl
@@ -58,12 +58,15 @@
".class" => { TOKEN(DOT); TOKEN_V(ID, tr_intern("class")); };
# ponctuation
+ "=>" => { TOKEN(HASHI); };
"," => { TOKEN(COMMA); };
"(" => { TOKEN(O_PAR); };
")" => { TOKEN(C_PAR); };
id "[" => { TOKEN_V(ID, tr_intern(BUFFER(ts, te-ts-1))); TOKEN(O_SBRA_ID); };
"[" => { TOKEN(O_SBRA); };
"]" => { TOKEN(C_SBRA); };
+ "{" => { TOKEN(O_CBRA); };
+ "}" => { TOKEN(C_CBRA); };
term => { TOKEN_U(TERM); };
dot => { TOKEN(DOT); };
View
11 vm/tr.h
@@ -22,6 +22,7 @@
#define TR_CCLASS(X) TR_CTYPE(X,Class)
#define TR_CFIXNUM(X) TR_CTYPE(X,Fixnum)
#define TR_CARRAY(X) TR_CTYPE(X,Array)
+#define TR_CHASH(X) TR_CTYPE(X,Hash)
#define TR_CSTRING(X) (assert(TR_IS_A(X,String)||TR_IS_A(X,Symbol)),(TrString*)(X))
#define TR_CMETHOD(X) ((TrMethod*)X)
@@ -178,6 +179,11 @@ typedef struct {
kvec_t(OBJ) kv;
} TrArray;
+typedef struct {
+ TR_OBJECT_HEADER;
+ khash_t(OBJ) *kh;
+} TrHash;
+
/* vm */
TrVM *TrVM_new();
void TrVM_start(VM, TrBlock *b);
@@ -205,6 +211,11 @@ OBJ TrArray_new2(VM, int argc, ...);
OBJ TrArray_new3(VM, int argc, OBJ items[]);
void TrArray_init(VM);
+/* hash */
+OBJ TrHash_new(VM);
+OBJ TrHash_new2(VM, size_t n, OBJ items[]);
+void TrHash_init(VM);
+
/* object */
OBJ TrObject_new(VM);
OBJ TrObject_method(VM, OBJ self, OBJ name);
View
2  vm/vm.c
@@ -162,6 +162,7 @@ OBJ TrVM_step(VM) {
OP(NIL): R[A] = TR_NIL; DISPATCH;
OP(BOOL): R[A] = B+1; DISPATCH;
OP(NEWARRAY): R[A] = TrArray_new3(vm, B, &R[A+1]); DISPATCH;
+ OP(NEWHASH): R[A] = TrHash_new2(vm, B, &R[A+1]); DISPATCH;
OP(RETURN): return R[A];
/* variable and consts */
@@ -247,6 +248,7 @@ TrVM *TrVM_new() {
TrString_init(vm);
TrFixnum_init(vm);
TrArray_init(vm);
+ TrHash_init(vm);
return vm;
}
Please sign in to comment.
Something went wrong with that request. Please try again.