Fix (reduce) with lambdas.
Fix await memory leak. Allow running specific tests with --run-test x (for valgrinding).
This commit is contained in:
parent
5a34bcbfbd
commit
7b014ebafa
32
src/env.c
32
src/env.c
|
@ -135,6 +135,7 @@ void deleteEnv(struct Environment* e)
|
||||||
if (e->refs) {
|
if (e->refs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->outer) {
|
if (e->outer) {
|
||||||
deleteEnv(e->outer);
|
deleteEnv(e->outer);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +226,7 @@ struct Environment defaultEnv()
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) {
|
for (i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) {
|
||||||
addFunc(symFuncs[i].sym, symFuncs[i].func, &e, i);
|
addFunc(symFuncs[i].sym, symFuncs[i].func, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
helpInitialized = 1;
|
helpInitialized = 1;
|
||||||
|
@ -272,12 +273,10 @@ void printEnv(struct Environment* env, int printPointers)
|
||||||
|
|
||||||
void addFunc(const char* name,
|
void addFunc(const char* name,
|
||||||
Object (* func)(Object*, int, struct Environment*),
|
Object (* func)(Object*, int, struct Environment*),
|
||||||
struct Environment* env,
|
struct Environment* env)
|
||||||
int i)
|
|
||||||
{
|
{
|
||||||
Object o = newObject(TYPE_FUNC);
|
Object o = newObject(TYPE_FUNC);
|
||||||
o.func = func;
|
o.func = func;
|
||||||
// addToEnvAt(i, env, name, o);
|
|
||||||
addToEnv(env, name, o);
|
addToEnv(env, name, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,13 +426,22 @@ Object help(Object* params, int length, struct Environment* env)
|
||||||
return nullTerminated("Help not found!");
|
return nullTerminated("Help not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns number of failures
|
// Returns number of failures, or -1 if the requested specificTest is invalid
|
||||||
int runTests(int detailed)
|
int runTests(int detailed, int specificTest)
|
||||||
{
|
{
|
||||||
printf("[35;1m::NATIVE TESTS::[0m\n");
|
int isSpecific = specificTest != -1;
|
||||||
|
if (specificTest >= currentHelp) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSpecific) {
|
||||||
|
printf("[35;1m::NATIVE TESTS::[0m\n");
|
||||||
|
}
|
||||||
int failureCount = 0;
|
int failureCount = 0;
|
||||||
int passCount = 0;
|
int passCount = 0;
|
||||||
for (int hi = 0; hi < currentHelp; hi++) {
|
int start = isSpecific ? specificTest : 0;
|
||||||
|
int end = isSpecific ? specificTest + 1 : currentHelp;
|
||||||
|
for (int hi = start; hi < end; hi++) {
|
||||||
struct helpText h = helpTexts[hi];
|
struct helpText h = helpTexts[hi];
|
||||||
if (h.tests) {
|
if (h.tests) {
|
||||||
if (detailed && h.testCount > 0) {
|
if (detailed && h.testCount > 0) {
|
||||||
|
@ -476,11 +484,15 @@ int runTests(int detailed)
|
||||||
if (passCount > 0) {
|
if (passCount > 0) {
|
||||||
printf("[32;1m");
|
printf("[32;1m");
|
||||||
}
|
}
|
||||||
printf("%d tests passed![0m\n", passCount);
|
if (!isSpecific) {
|
||||||
|
printf("%d tests passed![0m\n", passCount);
|
||||||
|
}
|
||||||
if (failureCount > 0) {
|
if (failureCount > 0) {
|
||||||
printf("[31m");
|
printf("[31m");
|
||||||
}
|
}
|
||||||
printf("%d tests failed![0m\n", failureCount);
|
if (!isSpecific || failureCount != 0) {
|
||||||
|
printf("%d tests failed![0m\n", failureCount);
|
||||||
|
}
|
||||||
// fprintf(stderr, "TOTAL ALLOCATIONS: %d\n", getAllocations());
|
// fprintf(stderr, "TOTAL ALLOCATIONS: %d\n", getAllocations());
|
||||||
// fprintf(stderr, "TOTAL BYTES: %zu\n", getBytes());
|
// fprintf(stderr, "TOTAL BYTES: %zu\n", getBytes());
|
||||||
return failureCount;
|
return failureCount;
|
||||||
|
|
|
@ -39,8 +39,7 @@ void printEnv(struct Environment* env, int printPointers);
|
||||||
|
|
||||||
void addFunc(const char* name,
|
void addFunc(const char* name,
|
||||||
Object (* func)(Object*, int, struct Environment*),
|
Object (* func)(Object*, int, struct Environment*),
|
||||||
struct Environment* env,
|
struct Environment* env);
|
||||||
int i);
|
|
||||||
|
|
||||||
void deleteEnv(struct Environment* e);
|
void deleteEnv(struct Environment* e);
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ void addStructDef(struct StructDef def);
|
||||||
|
|
||||||
void printColored(const char* code);
|
void printColored(const char* code);
|
||||||
|
|
||||||
int runTests(int detailed);
|
int runTests(int detailed, int specificTest);
|
||||||
|
|
||||||
int getTotalSearchDepth();
|
int getTotalSearchDepth();
|
||||||
|
|
||||||
|
|
46
src/hash.c
46
src/hash.c
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void addStripped(struct ObjectTable* table, char* name, struct StrippedObject object);
|
size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject object);
|
||||||
|
|
||||||
Object deStrip(struct StrippedObject object)
|
Object deStrip(struct StrippedObject object)
|
||||||
{
|
{
|
||||||
|
@ -43,30 +43,32 @@ void deleteTable(struct ObjectTable* table)
|
||||||
|
|
||||||
#ifndef HASHLESS_ENV
|
#ifndef HASHLESS_ENV
|
||||||
|
|
||||||
static unsigned long hash(const char* str, struct ObjectTable* table)
|
static size_t hash(const char* str, struct ObjectTable* table)
|
||||||
{
|
{
|
||||||
unsigned long hash = 5381;
|
size_t hash = 5381;
|
||||||
int c;
|
char c;
|
||||||
|
|
||||||
while ((c = *str++)) {
|
while ((c = *str++)) {
|
||||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash % table->capacity;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void extendTable(struct ObjectTable* table)
|
void extendTable(struct ObjectTable* table)
|
||||||
{
|
{
|
||||||
if (table->capacity < (table->count + 1) * 2) {
|
if (table->capacity >= (table->count + 1) * 2) {
|
||||||
struct ObjectTable newTable = buildTable(table->capacity ? table->capacity * 2 : 4);
|
return;
|
||||||
for (int i = 0; i < table->capacity; i++) {
|
|
||||||
if (table->elements[i].symbol) {
|
|
||||||
addStripped(&newTable, table->elements[i].symbol, table->elements[i].object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(table->elements);
|
|
||||||
*table = newTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ObjectTable newTable = buildTable(table->capacity ? table->capacity * 2 : 4);
|
||||||
|
for (int i = 0; i < table->capacity; i++) {
|
||||||
|
if (table->elements[i].symbol) {
|
||||||
|
addStripped(&newTable, table->elements[i].symbol, table->elements[i].object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(table->elements);
|
||||||
|
*table = newTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name)
|
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name)
|
||||||
|
@ -74,7 +76,7 @@ struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name)
|
||||||
if (table->capacity == 0) {
|
if (table->capacity == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
size_t h = hash(name, table);
|
size_t h = hash(name, table) % table->capacity;
|
||||||
while (table->elements[h].symbol) {
|
while (table->elements[h].symbol) {
|
||||||
if (strcmp(name, table->elements[h].symbol) == 0) {
|
if (strcmp(name, table->elements[h].symbol) == 0) {
|
||||||
return &table->elements[h].object;
|
return &table->elements[h].object;
|
||||||
|
@ -103,7 +105,7 @@ void extendTable(struct ObjectTable* table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object* getFromTable(struct ObjectTable* table, const char* name)
|
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < table->count; i++) {
|
for (size_t i = 0; i < table->count; i++) {
|
||||||
if (strcmp(name, table->elements[i].symbol) == 0) {
|
if (strcmp(name, table->elements[i].symbol) == 0) {
|
||||||
|
@ -113,32 +115,34 @@ Object* getFromTable(struct ObjectTable* table, const char* name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long hash(unused const char* str, struct ObjectTable* table)
|
static size_t hash(unused const char* str, struct ObjectTable* table)
|
||||||
{
|
{
|
||||||
return table->count;
|
return table->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void addStripped(struct ObjectTable* table, char* name, struct StrippedObject object)
|
size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject object)
|
||||||
{
|
{
|
||||||
extendTable(table);
|
extendTable(table);
|
||||||
size_t h = hash(name, table);
|
size_t initial = hash(name, table);
|
||||||
|
size_t h = initial % table->capacity;
|
||||||
while (table->elements[h].symbol) {
|
while (table->elements[h].symbol) {
|
||||||
h = (h + 1) % table->capacity;
|
h = (h + 1) % table->capacity;
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
return initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \param table
|
/// \param table
|
||||||
/// \param name Should be a new allocation
|
/// \param name Should be a new allocation
|
||||||
/// \param object Should already be cloned
|
/// \param object Should already be cloned
|
||||||
void addToTable(struct ObjectTable* table, char* name, Object object)
|
size_t addToTable(struct ObjectTable* table, char* name, Object object)
|
||||||
{
|
{
|
||||||
addStripped(table, name, (struct StrippedObject) {
|
return addStripped(table, name, (struct StrippedObject) {
|
||||||
.data = object.data,
|
.data = object.data,
|
||||||
.type = object.type,
|
.type = object.type,
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,10 @@ struct ObjectTable {
|
||||||
|
|
||||||
struct ObjectTable buildTable(size_t capacity);
|
struct ObjectTable buildTable(size_t capacity);
|
||||||
|
|
||||||
void addToTable(struct ObjectTable* table, char* name, Object object);
|
/// Returns the hash of the inserted object
|
||||||
|
size_t addToTable(struct ObjectTable* table, char* name, Object object);
|
||||||
|
|
||||||
|
struct StrippedObject* getWithHash(struct ObjectTable* table, size_t hash);
|
||||||
|
|
||||||
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name);
|
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name);
|
||||||
|
|
||||||
|
|
10
src/main.c
10
src/main.c
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
int runTests;
|
int runTests;
|
||||||
|
long specificTest;
|
||||||
int ignoreConfig;
|
int ignoreConfig;
|
||||||
int ignoreLib;
|
int ignoreLib;
|
||||||
int moreToDo;
|
int moreToDo;
|
||||||
|
@ -183,6 +184,7 @@ void setupSegfaultHandler()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SPECIFIC_TEST_ARG "--run-test"
|
||||||
#define RUN_TESTS_ARG "--run-tests"
|
#define RUN_TESTS_ARG "--run-tests"
|
||||||
#define RUN_DETAILED_TESTS "=detailed"
|
#define RUN_DETAILED_TESTS "=detailed"
|
||||||
#define IGNORE_CONFIG_ARG "--ignore-config"
|
#define IGNORE_CONFIG_ARG "--ignore-config"
|
||||||
|
@ -194,6 +196,7 @@ void getSettings(int argc, const char* argv[])
|
||||||
const char* const home = getenv("HOME");
|
const char* const home = getenv("HOME");
|
||||||
|
|
||||||
settings.runTests = 0;
|
settings.runTests = 0;
|
||||||
|
settings.specificTest = -1;
|
||||||
settings.ignoreConfig = 0;
|
settings.ignoreConfig = 0;
|
||||||
settings.ignoreLib = 0;
|
settings.ignoreLib = 0;
|
||||||
settings.moreToDo = 0;
|
settings.moreToDo = 0;
|
||||||
|
@ -203,12 +206,17 @@ void getSettings(int argc, const char* argv[])
|
||||||
|
|
||||||
size_t runTestsLen = strlen(RUN_TESTS_ARG);
|
size_t runTestsLen = strlen(RUN_TESTS_ARG);
|
||||||
size_t configFileLen = strlen(CONFIG_FILE_ARG);
|
size_t configFileLen = strlen(CONFIG_FILE_ARG);
|
||||||
|
size_t specificTestLen = strlen(SPECIFIC_TEST_ARG);
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (strncmp(argv[i], RUN_TESTS_ARG, runTestsLen) == 0) {
|
if (strncmp(argv[i], RUN_TESTS_ARG, runTestsLen) == 0) {
|
||||||
int isDetailed = strcmp(argv[i] + runTestsLen, RUN_DETAILED_TESTS) == 0;
|
int isDetailed = strcmp(argv[i] + runTestsLen, RUN_DETAILED_TESTS) == 0;
|
||||||
settings.runTests = isDetailed ? 2 : 1;
|
settings.runTests = isDetailed ? 2 : 1;
|
||||||
} else if (strncmp(argv[i], CONFIG_FILE_ARG, configFileLen) == 0) {
|
} else if (strncmp(argv[i], CONFIG_FILE_ARG, configFileLen) == 0) {
|
||||||
settings.configFile = argv[i] + configFileLen;
|
settings.configFile = argv[i] + configFileLen;
|
||||||
|
} else if (strncmp(argv[i], SPECIFIC_TEST_ARG, specificTestLen) == 0) {
|
||||||
|
settings.runTests = 2;
|
||||||
|
char* invalid;
|
||||||
|
settings.specificTest = strtol(argv[i + 1], &invalid, 10);
|
||||||
} else if (strcmp(argv[i], IGNORE_CONFIG_ARG) == 0) {
|
} else if (strcmp(argv[i], IGNORE_CONFIG_ARG) == 0) {
|
||||||
settings.ignoreConfig = 1;
|
settings.ignoreConfig = 1;
|
||||||
} else if (strcmp(argv[i], IGNORE_LIB_ARG) == 0) {
|
} else if (strcmp(argv[i], IGNORE_LIB_ARG) == 0) {
|
||||||
|
@ -230,7 +238,7 @@ int main(int argc, const char* argv[])
|
||||||
setGlobal(&env);
|
setGlobal(&env);
|
||||||
|
|
||||||
if (settings.runTests) {
|
if (settings.runTests) {
|
||||||
int ret = runTests(settings.runTests == 2);
|
int ret = runTests(settings.runTests == 2, settings.specificTest);
|
||||||
shredDictionary();
|
shredDictionary();
|
||||||
deleteEnv(global());
|
deleteEnv(global());
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -141,17 +141,6 @@ Object listEvalFunc(const Object* function, const Object* paramList,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object simpleFuncEval(const Object func, Object arg1, Object arg2, struct Environment* env)
|
|
||||||
{
|
|
||||||
arg2 = cloneObject(arg2);
|
|
||||||
arg1.forward = &arg2;
|
|
||||||
Object first_eval = eval(&func, env);
|
|
||||||
Object ret = funcyEval(&first_eval, &arg1, 2, env);
|
|
||||||
cleanObject(&first_eval);
|
|
||||||
cleanObject(&arg2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a list whose first element is a lambda, applying that lambda
|
* Evaluates a list whose first element is a lambda, applying that lambda
|
||||||
*
|
*
|
||||||
|
@ -180,6 +169,14 @@ Object listEvalLambda(Object* lambda, const Object* passedArguments, int evalLen
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a func-like object with the given parameters
|
||||||
|
* @param funcy The func-like. Should be a fresh object! Will be freed!
|
||||||
|
* @param passedArguments Ongoing (forward->forward) list of arguments.
|
||||||
|
* @param evalLength Number of parameters to the func-like object.
|
||||||
|
* @param env
|
||||||
|
* @return The result from the func-like object.
|
||||||
|
*/
|
||||||
Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength,
|
Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength,
|
||||||
struct Environment* env)
|
struct Environment* env)
|
||||||
{
|
{
|
||||||
|
@ -300,7 +297,7 @@ Object eval(const Object* obj, struct Environment* env)
|
||||||
return evalList(obj, env);
|
return evalList(obj, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
return errorObject(BAD_TYPE);
|
return errorWithContext(BAD_TYPE, "eval()");
|
||||||
}
|
}
|
||||||
|
|
||||||
Object structAccess(Object* params, unused int length, unused struct Environment* env)
|
Object structAccess(Object* params, unused int length, unused struct Environment* env)
|
||||||
|
|
|
@ -83,8 +83,6 @@ Object listEvalLambda(Object* lambda, const Object* passedArguments, int evalLen
|
||||||
Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength,
|
Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength,
|
||||||
struct Environment* env);
|
struct Environment* env);
|
||||||
|
|
||||||
Object simpleFuncEval(Object func, Object arg1, Object arg2, struct Environment* env);
|
|
||||||
|
|
||||||
Object typeCheck(const char* funcName, Object* params, int length,
|
Object typeCheck(const char* funcName, Object* params, int length,
|
||||||
struct TypeCheck typeChecks[], int typeLength, int* failed);
|
struct TypeCheck typeChecks[], int typeLength, int* failed);
|
||||||
|
|
||||||
|
|
21
src/plfunc.c
21
src/plfunc.c
|
@ -8,21 +8,24 @@ Object reduce(Object* params, unused int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
checkTypes(reduce)
|
checkTypes(reduce)
|
||||||
Object list = params[0];
|
Object list = params[0];
|
||||||
const Object func = params[1];
|
Object func = params[1];
|
||||||
Object total = params[2];
|
Object total = params[2];
|
||||||
|
|
||||||
if (list.type != TYPE_LIST) {
|
if (list.type != TYPE_LIST) {
|
||||||
return simpleFuncEval(func, total, list, env);
|
func = cloneObject(func);
|
||||||
|
list.forward = &total;
|
||||||
|
return funcyEval(&func, &list, 2, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
int isFirst = 1;
|
Object* first = list.list;
|
||||||
FOR_POINTER_IN_LIST(&list) {
|
FOR_POINTER_IN_LIST(&list) {
|
||||||
|
func = cloneObject(func);
|
||||||
Object oldTotal = total;
|
Object oldTotal = total;
|
||||||
total = simpleFuncEval(func, total, *POINTER, env);
|
total.forward = POINTER;
|
||||||
if (!isFirst) {
|
total = funcyEval(&func, &total, 2, env);
|
||||||
|
if (POINTER != first) {
|
||||||
cleanObject(&oldTotal);
|
cleanObject(&oldTotal);
|
||||||
}
|
}
|
||||||
isFirst = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
|
@ -560,7 +563,11 @@ Object readFileToObject(Object* params, unused int length, unused struct Environ
|
||||||
Object getEnvVar(Object* params, unused int length, unused struct Environment* env)
|
Object getEnvVar(Object* params, unused int length, unused struct Environment* env)
|
||||||
{
|
{
|
||||||
checkTypes(getEnvVar)
|
checkTypes(getEnvVar)
|
||||||
return nullTerminated(getenv(params[0].string));
|
const char* envVar = getenv(params[0].string);
|
||||||
|
if (envVar) {
|
||||||
|
return nullTerminated(envVar);
|
||||||
|
}
|
||||||
|
return stringFromSlice("", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STANDALONE
|
#endif // STANDALONE
|
||||||
|
|
12
src/plfunc.h
12
src/plfunc.h
|
@ -102,13 +102,15 @@ tfn(len, "len",
|
||||||
|
|
||||||
tfn(reduce, "reduce",
|
tfn(reduce, "reduce",
|
||||||
({ anyType, expect(isFuncy), anyType, anyType }),
|
({ anyType, expect(isFuncy), anyType, anyType }),
|
||||||
"Performs a simple reduction. Does not currently work with lambdas.\n" // TODO: Still not working
|
"Performs a simple reduction.\n"
|
||||||
"Takes three arguments:\n"
|
"Takes three arguments:\n"
|
||||||
" - Values\n"
|
" - Values\n"
|
||||||
" - A function to apply to each value\n"
|
" - A function to apply to each value\n"
|
||||||
" - An initial value",
|
" - An initial value",
|
||||||
"(reduce 5 + 6)", "11",
|
"(reduce 5 + 6)", "11",
|
||||||
"(reduce (1 2 3) + 0)", "6",
|
"(reduce (1 2 3) + 0)", "6",
|
||||||
|
"(def sum (fn (left right) ((+ left right)) )) (reduce 5 sum 6)", "11",
|
||||||
|
"(def sum (fn (left right) ((+ left right)) )) (reduce (1 2 3) sum 0)", "6",
|
||||||
);
|
);
|
||||||
|
|
||||||
tfn(at, "at",
|
tfn(at, "at",
|
||||||
|
@ -263,12 +265,14 @@ tfn(systemCall, "sys",
|
||||||
|
|
||||||
tfn(cd, "cd",
|
tfn(cd, "cd",
|
||||||
({ expect(isStringy), anyType }),
|
({ expect(isStringy), anyType }),
|
||||||
"Change the current directory."
|
"Change the current directory.",
|
||||||
|
"(cd \"/\") (cwd)", "/"
|
||||||
);
|
);
|
||||||
|
|
||||||
tfn(cwd, "cwd",
|
tfn(cwd, "cwd",
|
||||||
({ returns(isStringy) }),
|
({ returns(isStringy) }),
|
||||||
"Get the current directory."
|
"Get the current directory.",
|
||||||
|
"(cd \"/\") (cwd)", "/"
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @code
|
/// @code
|
||||||
|
@ -277,7 +281,7 @@ tfn(cwd, "cwd",
|
||||||
fn(takeInput, "inp",
|
fn(takeInput, "inp",
|
||||||
"Take console input with an optional prompt. For example:\n"
|
"Take console input with an optional prompt. For example:\n"
|
||||||
"`(def x (input))` will wait for user input with no prompt.\n"
|
"`(def x (input))` will wait for user input with no prompt.\n"
|
||||||
"`(def x (input \">> \"))` wait for input, but prompt the user with '>> '.\n"
|
"`(def x (input \">> \"))` wait for input, but prompt the user with '>> '\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
tfn(readFileToObject, "rf",
|
tfn(readFileToObject, "rf",
|
||||||
|
|
|
@ -274,7 +274,14 @@ echo "$TOTAL_FAILS Tests Failed[0m"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if $VALGRIND; then
|
if $VALGRIND; then
|
||||||
$VALCOM ./pl --run-tests=detailed
|
i=0
|
||||||
|
while true; do
|
||||||
|
valgrind -q --leak-check=full --error-exitcode=1 --track-origins=yes ./pl --run-test $i
|
||||||
|
if [[ "$?" == "255" ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
else
|
else
|
||||||
./pl --run-tests
|
./pl --run-tests
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -75,7 +75,6 @@ Object async(Object* params, int length, struct Environment* env)
|
||||||
.env = env,
|
.env = env,
|
||||||
.object = cloneObject(params[0]),
|
.object = cloneObject(params[0]),
|
||||||
};
|
};
|
||||||
env->refs += 1;
|
|
||||||
|
|
||||||
pthread_create(&promise.promise->thread, NULL, doAsync, promise.promise);
|
pthread_create(&promise.promise->thread, NULL, doAsync, promise.promise);
|
||||||
return promise;
|
return promise;
|
||||||
|
|
Loading…
Reference in New Issue