Start work on hash-table objects.

This commit is contained in:
Sage Vaillancourt 2022-04-18 16:59:29 -04:00 committed by Sage Vaillancourt
parent 4ea3b1d36d
commit 8e30b24e8f
9 changed files with 159 additions and 74 deletions

View File

@ -237,7 +237,10 @@ struct Environment defaultEnv()
pf(getEnvVar), pf(getEnvVar),
pf(async), pf(async),
pf(await), pf(await),
pf(help) pf(help),
pf(buildHashTable),
pf(addToHashTable),
pf(getFromHashTable)
#endif #endif
}; };

View File

@ -61,20 +61,6 @@ void printColored(const char* code);
int runTests(int detailed, int specificTest); int runTests(int detailed, int specificTest);
#define unused __attribute__((unused))
#define array_length(_array) (sizeof(_array) / sizeof((_array)[0]))
#define fnn(_name, _docs, ...) \
static const char * const _name ## Doc = _docs; \
unused static const char * const _name ## Tests[] = {__VA_ARGS__}; \
_Static_assert(array_length(_name ## Tests) % 2 == 0, "Array of test strings must have exactly one expected result for each test."); \
Object _name(Object* params, int length, struct Environment* env)
#define fn(_name, _symbol, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
fn(segfault, "seg", fn(segfault, "seg",
"Induces a segfault." "Induces a segfault."
); );

View File

@ -30,7 +30,7 @@
(stkadd bottom) (stkadd bottom)
))) )))
(def words (fn (text) ( (def get-words (fn (text) (
(split text " ") (split text " ")
))) )))
@ -46,9 +46,18 @@
(prnl (pop)) (prnl (pop))
))) )))
(def fmap (fn (word) ( (def compile (fn (words) (
;(prnl (cat "fmap: " word)) (def name (at 0 words))
(set words (rest words))
(def name ())
)))
(def _fmap (fn (words) (
;(prnl (cat "fmap: " word))
(def word (at 0 words))
(if (iserr word) () (
(if (= ":" word) (compile (words))
(if (= "swap" word) (swap) (if (= "swap" word) (swap)
(if (= "??" word) (pstack) (if (= "??" word) (pstack)
(if (= "+" word) (twop +) (if (= "+" word) (twop +)
@ -57,16 +66,20 @@
(if (= "*" word) (twop *) (if (= "*" word) (twop *)
(if (= "." word) (loud-pop) (if (= "." word) (loud-pop)
(stkadd (eval word)) (stkadd (eval word))
))))))) ))))))))
))) (_fmap (rest words))
(def repl (fn () (
(def z (inp "plf:> "))
(if (= z "q") () (
(for-each fmap (words z))
(prn nl)
(repl)
)) ))
))) )))
(repl) (def fmap (fn (text) (
(def words (get-words text))
(_fmap words)
)))
; Override the normal REPL prompt
(set prompt "plf:> ")
(set preprocess (fn (text) (
(fmap text)
(prn nl)
"" ; Have the underlying REPL do nothing
)))

View File

@ -2,6 +2,7 @@
#include "env.h" #include "env.h"
#include <string.h> #include <string.h>
#include <stdio.h>
size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject object); size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject object);
@ -130,6 +131,7 @@ size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject
while (table->elements[h].symbol) { while (table->elements[h].symbol) {
h = (h + 1) % table->capacity; h = (h + 1) % table->capacity;
} }
eprintf("adding at %d: `%s`\n", h, name);
table->elements[h].symbol = name; table->elements[h].symbol = name;
table->elements[h].object = object; table->elements[h].object = object;
table->count += 1; table->count += 1;
@ -147,3 +149,43 @@ size_t addToTable(struct ObjectTable* table, char* name, Object object)
.type = object.type, .type = object.type,
}); });
} }
#ifdef STANDALONE
Object buildHashTable(Object* params, int length, struct Environment* env)
{
long capacity = 16;
if (length > 0 && params[0].type == TYPE_NUMBER) {
capacity = params[0].number;
}
Object table = newObject(TYPE_HASH_TABLE);
table.table = malloc(sizeof(struct ObjectTableObject));
table.table->table = buildTable(capacity);
table.table->refs = 2;
return table;
}
Object addToHashTable(Object* params, int length, struct Environment* env)
{
Object table = params[0];
Object name = params[1];
Object add = params[2];
eprintf("Adding `%s`\n", name.string);
addToTable(&table.table->table, name.string, cloneObject(add));
return numberObject(0);
}
Object getFromHashTable(Object* params, int length, struct Environment* env)
{
struct ObjectTable* table = &params[0].table->table;
for (int i = 0; i < table->capacity; i++) {
eprintf("[%d] %s\n", i, table->elements[i].symbol);
}
struct StrippedObject* fetched = getFromTable(&params[0].table->table, params[1].string);
if (fetched) {
return deStrip(*fetched);
}
throw(DID_NOT_FIND_SYMBOL, "Hash table does not contain %s", params[1].string);
}
#endif

View File

@ -20,4 +20,25 @@ struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name)
void deleteTable(struct ObjectTable* table); void deleteTable(struct ObjectTable* table);
#ifdef STANDALONE
struct ObjectTableObject {
struct ObjectTable table;
int refs;
};
fn(buildHashTable, "table",
"Create a hash table object."
);
fn(addToHashTable, "h-insert",
"Insert into a hash table object."
);
fn(getFromHashTable, "h-get",
"Get a value from a hash table object."
);
#endif
#endif //PEBBLISP_HASH_H #endif //PEBBLISP_HASH_H

View File

@ -262,6 +262,9 @@ int stringNObj(struct string* s, const Object* obj)
case TYPE_STATIC_FUNC: case TYPE_STATIC_FUNC:
appendf(s, "STATIC FUNC"); appendf(s, "STATIC FUNC");
break; break;
case TYPE_HASH_TABLE:
appendf(s, "HASH TABLE");
break;
case TYPE_STRUCT: case TYPE_STRUCT:
stringStruct(s, obj); stringStruct(s, obj);
break; break;
@ -358,6 +361,7 @@ const char* getTypeName(const Object* obj)
SIMPLE_TYPE(TYPE_STATIC_FUNC); SIMPLE_TYPE(TYPE_STATIC_FUNC);
SIMPLE_TYPE(TYPE_SYMBOL); SIMPLE_TYPE(TYPE_SYMBOL);
SIMPLE_TYPE(TYPE_STRING); SIMPLE_TYPE(TYPE_STRING);
SIMPLE_TYPE(TYPE_HASH_TABLE);
SIMPLE_TYPE(TYPE_PROMISE); SIMPLE_TYPE(TYPE_PROMISE);
SIMPLE_TYPE(TYPE_OTHER); SIMPLE_TYPE(TYPE_OTHER);
SIMPLE_TYPE(TYPE_ERROR); SIMPLE_TYPE(TYPE_ERROR);
@ -422,6 +426,13 @@ void cleanObject(Object* target)
case TYPE_SLIST: case TYPE_SLIST:
deleteList(target); deleteList(target);
break; break;
case TYPE_HASH_TABLE:
target->table->refs -= 1;
if (!target->table->refs) {
deleteTable(&target->table->table);
free(target->table);
}
break;
case TYPE_LAMBDA: case TYPE_LAMBDA:
target->lambda->refs -= 1; target->lambda->refs -= 1;
if (!target->lambda->refs) { if (!target->lambda->refs) {
@ -627,6 +638,7 @@ inline int isValidType(const Object test)
case TYPE_SYMBOL: case TYPE_SYMBOL:
case TYPE_LAMBDA: case TYPE_LAMBDA:
case TYPE_STRING: case TYPE_STRING:
case TYPE_HASH_TABLE:
case TYPE_PROMISE: case TYPE_PROMISE:
case TYPE_OTHER: case TYPE_OTHER:
case TYPE_ERROR: case TYPE_ERROR:
@ -674,8 +686,12 @@ inline Object cloneObject(const Object src)
return errorWithContext(getErrorCode(src), src.error->context); return errorWithContext(getErrorCode(src), src.error->context);
case TYPE_OTHER: case TYPE_OTHER:
return cloneOther(src); return cloneOther(src);
case TYPE_HASH_TABLE:
src.table->refs += 1;
return src;
case TYPE_STATIC_FUNC: case TYPE_STATIC_FUNC:
src.staticF->refs += 1; src.staticF->refs += 1;
return src;
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_NUMBER: case TYPE_NUMBER:
case TYPE_FUNC: case TYPE_FUNC:

View File

@ -40,6 +40,45 @@
#define SIMPLE_ERRORS #define SIMPLE_ERRORS
#endif #endif
#define unused __attribute__((unused))
#define array_length(_array) (sizeof(_array) / sizeof((_array)[0]))
#define UNPACK(...) __VA_ARGS__
#ifdef STANDALONE
#define fnn(_name, _docs, ...) \
static const char * const _name ## Doc = _docs; \
unused static const char * const _name ## Tests[] = {__VA_ARGS__}; \
_Static_assert(array_length(_name ## Tests) % 2 == 0, "Array of test strings must have exactly one expected result for each test."); \
Object _name(Object* params, int length, struct Environment* env)
#define expect(_checker) {.checkFunc = (_checker), .name = #_checker}
#define returns(_checker) {.checkFunc = (_checker), .name = #_checker}
#define anyType {.checkFunc = NULL, .name = "AnyType"}
#define tfn(_name, _symbol, _type, _docs, ...) \
unused static struct TypeCheck _name ## TypeChecks[] = UNPACK _type; \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#define fn(_name, _symbol, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#else
#define fnn(_name, _docs, ...) \
Object _name(Object* params, int length, struct Environment* env)
#define tfn(_name, _symbol, _type, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#define fn(_name, _symbol, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#endif
enum errorCode { enum errorCode {
MISMATCHED_PARENS, MISMATCHED_PARENS,
NULL_ENV, NULL_ENV,
@ -73,6 +112,7 @@ typedef enum Type {
TYPE_SYMBOL, TYPE_SYMBOL,
TYPE_LAMBDA, TYPE_LAMBDA,
TYPE_STRING, TYPE_STRING,
TYPE_HASH_TABLE,
TYPE_PROMISE, TYPE_PROMISE,
TYPE_OTHER, TYPE_OTHER,
TYPE_ERROR TYPE_ERROR
@ -85,6 +125,7 @@ struct Environment;
struct Promise; struct Promise;
struct Other; struct Other;
struct StaticFunction; struct StaticFunction;
struct ObjectTableObject;
struct Error { struct Error {
enum errorCode code; enum errorCode code;
char* context; char* context;
@ -106,6 +147,7 @@ struct Object {
struct StaticFunction* staticF; struct StaticFunction* staticF;
struct Other* other; struct Other* other;
struct Promise* promise; struct Promise* promise;
struct ObjectTableObject* table;
#ifdef SIMPLE_ERRORS #ifdef SIMPLE_ERRORS
enum errorCode error; enum errorCode error;
#else #else

View File

@ -310,6 +310,7 @@ Object eval(const Object* obj, struct Environment* env)
case TYPE_STRING: case TYPE_STRING:
case TYPE_STRUCT: case TYPE_STRUCT:
case TYPE_SLIST: case TYPE_SLIST:
case TYPE_HASH_TABLE:
case TYPE_PROMISE: case TYPE_PROMISE:
return cloneObject(*obj); return cloneObject(*obj);

View File

@ -6,51 +6,12 @@
#include "env.h" #include "env.h"
#include "object.h" #include "object.h"
#define unused __attribute__((unused))
#define array_length(_array) (sizeof(_array) / sizeof((_array)[0]))
#define UNPACK(...) __VA_ARGS__
#ifdef STANDALONE
#define fnn(_name, _docs, ...) \
static const char * const _name ## Doc = _docs; \
unused static const char * const _name ## Tests[] = {__VA_ARGS__}; \
_Static_assert(array_length(_name ## Tests) % 2 == 0, "Array of test strings must have exactly one expected result for each test."); \
Object _name(Object* params, int length, struct Environment* env)
struct TypeCheck { struct TypeCheck {
int (* checkFunc)(Object); int (* checkFunc)(Object);
const char* name; const char* name;
}; };
#define expect(_checker) {.checkFunc = (_checker), .name = #_checker}
#define returns(_checker) {.checkFunc = (_checker), .name = #_checker}
#define anyType {.checkFunc = NULL, .name = "AnyType"}
#define tfn(_name, _symbol, _type, _docs, ...) \
unused static struct TypeCheck _name ## TypeChecks[] = UNPACK _type; \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#define fn(_name, _symbol, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#else
#define fnn(_name, _docs, ...) \
Object _name(Object* params, int length, struct Environment* env)
#define tfn(_name, _symbol, _type, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#define fn(_name, _symbol, _docs, ...) \
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#endif
#define trueObject() boolObject(1) #define trueObject() boolObject(1)
#define falseObject() boolObject(0) #define falseObject() boolObject(0)