1
0
mirror of https://github.com/janet-lang/janet synced 2025-10-25 04:37:42 +00:00

Add proto field to tables to allow prototypal inheritance.

This commit is contained in:
Calvin Rose
2018-03-10 13:34:46 -05:00
parent 0c3b0673ff
commit 0b6ac1698c
10 changed files with 71 additions and 39 deletions

View File

@@ -114,14 +114,17 @@
ret)
})
(defn onerr [t e]
(print (string t " error: " e)))
# Compile time
(var *read* nil)
(var *onvalue* identity)
(var *env* _env)
(def require-loading @{})
(defn onerr [t e]
(print (string t " error: " e)))
(defn char-stream [getchunk ondone]
(fiber (fn [parent]
(def buf @"")
@@ -197,7 +200,7 @@
(def wrapper (fiber (fn []
(while *read*
(def source (*read*))
(def res (compile source _env))
(def res (compile source *env*))
(if (= (type res) :function)
(*onvalue* (res))
(onerr "compile" (get res :error)))))))

View File

@@ -47,6 +47,9 @@ static const DstReg cfuns[] = {
{"buffer", dst_core_buffer},
{"gensym", dst_core_gensym},
{"get", dst_core_get},
{"rawget", dst_core_rawget},
{"getproto", dst_core_getproto},
{"setproto", dst_core_setproto},
{"put", dst_core_put},
{"length", dst_core_length},
{"gccollect", dst_core_gccollect},

View File

@@ -172,6 +172,33 @@ int dst_core_get(DstArgs args) {
return dst_return(args, ds);
}
int dst_core_rawget(DstArgs args) {
if (args.n != 2) return dst_throw(args, "expected 2 arguments");
if (!dst_checktype(args.v[0], DST_TABLE)) return dst_throw(args, "expected table");
return dst_return(args, dst_table_rawget(dst_unwrap_table(args.v[0]), args.v[1]));
}
int dst_core_getproto(DstArgs args) {
DstTable *t;
if (args.n != 1) return dst_throw(args, "expected 1 argument");
if (!dst_checktype(args.v[0], DST_TABLE)) return dst_throw(args, "expected table");
t = dst_unwrap_table(args.v[0]);
return dst_return(args, t->proto
? dst_wrap_table(t->proto)
: dst_wrap_nil());
}
int dst_core_setproto(DstArgs args) {
if (args.n != 2) return dst_throw(args, "expected 2 arguments");
if (!dst_checktype(args.v[0], DST_TABLE)) return dst_throw(args, "expected table");
if (!dst_checktype(args.v[1], DST_TABLE) && !dst_checktype(args.v[1], DST_NIL))
return dst_throw(args, "expected table");
dst_unwrap_table(args.v[0])->proto = dst_checktype(args.v[1], DST_TABLE)
? dst_unwrap_table(args.v[1])
: NULL;
return dst_return(args, args.v[0]);
}
int dst_core_fiber_status(DstArgs args) {
const char *status = "";
if (args.n != 1) return dst_throw(args, "expected 1 argument");

View File

@@ -109,10 +109,15 @@ static void dst_mark_array(DstArray *array) {
}
static void dst_mark_table(DstTable *table) {
recur: /* Manual tail recursion */
if (dst_gc_reachable(table))
return;
dst_gc_mark(table);
dst_mark_kvs(table->data, table->capacity);
if (table->proto) {
table = table->proto;
goto recur;
}
}
static void dst_mark_struct(const DstKV *st) {

View File

@@ -43,6 +43,7 @@ DstTable *dst_table_init(DstTable *table, int32_t capacity) {
}
table->count = 0;
table->deleted = 0;
table->proto = NULL;
return table;
}
@@ -114,8 +115,25 @@ static void dst_table_rehash(DstTable *t, int32_t size) {
free(olddata);
}
/* Get a value out of the object */
/* Get a value out of the table */
Dst dst_table_get(DstTable *t, Dst key) {
DstKV *bucket = dst_table_find(t, key);
if (NULL != bucket && !dst_checktype(bucket->key, DST_NIL))
return bucket->value;
/* Check prototypes */
{
int i;
for (i = DST_MAX_PROTO_DEPTH, t = t->proto; t && i; t = t->proto, --i) {
bucket = dst_table_find(t, key);
if (NULL != bucket && !dst_checktype(bucket->key, DST_NIL))
return bucket->value;
}
}
return dst_wrap_nil();
}
/* Get a value out of the table. Don't check prototype tables. */
Dst dst_table_rawget(DstTable *t, Dst key) {
DstKV *bucket = dst_table_find(t, key);
if (NULL != bucket && !dst_checktype(bucket->key, DST_NIL))
return bucket->value;

View File

@@ -120,6 +120,7 @@ DstTable *dst_table(int32_t capacity);
DstTable *dst_table_init(DstTable *table, int32_t capacity);
void dst_table_deinit(DstTable *table);
Dst dst_table_get(DstTable *t, Dst key);
Dst dst_table_rawget(DstTable *t, Dst key);
Dst dst_table_remove(DstTable *t, Dst key);
void dst_table_put(DstTable *t, Dst key, Dst value);
const DstKV *dst_table_next(DstTable *t, const DstKV *kv);

View File

@@ -120,6 +120,9 @@ extern "C" {
* ands crashing (the parser). Instead, error out. */
#define DST_RECURSION_GUARD 1024
/* Maximum depth to follow table prototypes before giving up and returning nil. */
#define DST_MAX_PROTO_DEPTH 200
/* Define max stack size for stacks before raising a stack overflow error.
* If this is not defined, fiber stacks can grow without limit (until memory
* runs out) */

View File

@@ -90,6 +90,9 @@ int dst_core_buffer(DstArgs args);
int dst_core_gensym(DstArgs args);
int dst_core_length(DstArgs args);
int dst_core_get(DstArgs args);
int dst_core_rawget(DstArgs args);
int dst_core_getproto(DstArgs args);
int dst_core_setproto(DstArgs args);
int dst_core_fiber_status(DstArgs args);
int dst_core_fiber_current(DstArgs args);
int dst_core_put(DstArgs args);

View File

@@ -359,6 +359,7 @@ struct DstBuffer {
/* A mutable associative data type. Backed by a hashtable. */
struct DstTable {
DstKV *data;
DstTable *proto;
int32_t count;
int32_t capacity;
int32_t deleted;