Use dynamically-sized strings for stringObj.
Fix webby.pl's `reduce` usage and web.c's struct creation.
This commit is contained in:
parent
af7a2e6265
commit
a444bc11bb
|
@ -42,7 +42,6 @@ Object fetchFromEnvironment(const char* name, struct Environment* env)
|
||||||
}
|
}
|
||||||
|
|
||||||
printd("Try %d (%s)\n", i, env->strings[i]);
|
printd("Try %d (%s)\n", i, env->strings[i]);
|
||||||
debugObj(&env->objects[i]);
|
|
||||||
if (strcmp(name, env->strings[i]) == 0) { printd("Returning!\n");
|
if (strcmp(name, env->strings[i]) == 0) { printd("Returning!\n");
|
||||||
return cloneObject(env->objects[i]);
|
return cloneObject(env->objects[i]);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +84,7 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms, i
|
||||||
for (int i = 0; i < paramCount; i++) {
|
for (int i = 0; i < paramCount; i++) {
|
||||||
const char* newObjName = itemAt(params, i)->string;
|
const char* newObjName = itemAt(params, i)->string;
|
||||||
// Eval the `march` list
|
// Eval the `march` list
|
||||||
Object newEnvObj = march ? eval(march, outer) : errorObject(NOT_ENOUGH_ARGUMENTS);
|
Object newEnvObj = march ? eval(march, outer) : errorWithContext(NOT_ENOUGH_ARGUMENTS, newObjName);
|
||||||
addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms?
|
addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms?
|
||||||
cleanObject(&newEnvObj);
|
cleanObject(&newEnvObj);
|
||||||
march = march ? march->forward : NULL;
|
march = march ? march->forward : NULL;
|
||||||
|
@ -324,7 +323,6 @@ int runTests(int detailed)
|
||||||
for (int hi = 0; hi < currentHelp; hi++) {
|
for (int hi = 0; hi < currentHelp; hi++) {
|
||||||
struct helpText h = helpTexts[hi];
|
struct helpText h = helpTexts[hi];
|
||||||
if (h.tests) {
|
if (h.tests) {
|
||||||
char result[1024];
|
|
||||||
if (detailed && h.testCount > 0) {
|
if (detailed && h.testCount > 0) {
|
||||||
printf("[0m `%s` ", h.symbol);
|
printf("[0m `%s` ", h.symbol);
|
||||||
}
|
}
|
||||||
|
@ -333,7 +331,8 @@ int runTests(int detailed)
|
||||||
const char* expected = h.tests[ti + 1];
|
const char* expected = h.tests[ti + 1];
|
||||||
struct Environment env = defaultEnv();
|
struct Environment env = defaultEnv();
|
||||||
Object o = parseEval(test, &env);
|
Object o = parseEval(test, &env);
|
||||||
stringObj(result, &o);
|
size_t length;
|
||||||
|
char* result = stringObj(&o, &length);
|
||||||
cleanObject(&o);
|
cleanObject(&o);
|
||||||
if (strcmp(result, expected) != 0) {
|
if (strcmp(result, expected) != 0) {
|
||||||
failureCount++;
|
failureCount++;
|
||||||
|
@ -346,6 +345,7 @@ int runTests(int detailed)
|
||||||
}
|
}
|
||||||
passCount++;
|
passCount++;
|
||||||
}
|
}
|
||||||
|
free(result);
|
||||||
deleteEnv(&env);
|
deleteEnv(&env);
|
||||||
}
|
}
|
||||||
if (detailed && h.testCount > 0) {
|
if (detailed && h.testCount > 0) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
(def element (fn (type)
|
(def element (fn (type)
|
||||||
(fn (text)
|
(fn (text)
|
||||||
(cat "<" type ">"
|
(cat "<" type ">"
|
||||||
(if (islist text) (reduce (text "") cat) (reduce ((text) "") cat))
|
(if (islist text) (reduce text cat "") (reduce (text) cat ""))
|
||||||
"</" type ">"))))
|
"</" type ">"))))
|
||||||
|
|
||||||
(def html (element "html"))
|
(def html (element "html"))
|
||||||
|
@ -49,10 +49,8 @@ stuff, when you think about it."
|
||||||
(htmlize p2)))
|
(htmlize p2)))
|
||||||
))))
|
))))
|
||||||
|
|
||||||
(def revealer (fn (x) (cat "" x)))
|
|
||||||
|
|
||||||
(get "/" homepage)
|
(get "/" homepage)
|
||||||
(get "/x" revealer)
|
(get "/x" (fn (req) (cat "" req)))
|
||||||
|
|
||||||
(def styles (rf "styles.css"))
|
(def styles (rf "styles.css"))
|
||||||
(get "/styles.css" (fn () (styles)))
|
(get "/styles.css" (fn () (styles)))
|
||||||
|
|
154
src/object.c
154
src/object.c
|
@ -145,6 +145,29 @@ static const char* errorText[] = {"MISMATCHED_PARENS",
|
||||||
"INDEX_PAST_END"};
|
"INDEX_PAST_END"};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
size_t inflate(struct string* s, size_t additional)
|
||||||
|
{
|
||||||
|
size_t length = (s->cursor - s->allocPoint) + additional;
|
||||||
|
|
||||||
|
int needsInflation = 0;
|
||||||
|
while (length > s->capacity - 8) {
|
||||||
|
s->capacity *= 2;
|
||||||
|
needsInflation = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsInflation) {
|
||||||
|
char* oldAlloc = s->allocPoint;
|
||||||
|
s->allocPoint = malloc(sizeof(char) * s->capacity);
|
||||||
|
size_t l = sprintf(s->allocPoint, "%s", oldAlloc);
|
||||||
|
s->cursor = s->allocPoint + l;
|
||||||
|
free(oldAlloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stringNObj(struct string *s, const Object* obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a string from a given list Object
|
* Creates a string from a given list Object
|
||||||
* Blocks out with parens
|
* Blocks out with parens
|
||||||
|
@ -152,52 +175,46 @@ static const char* errorText[] = {"MISMATCHED_PARENS",
|
||||||
* @param dest The string to copy the list text into
|
* @param dest The string to copy the list text into
|
||||||
* @param obj The list Object to make a string from
|
* @param obj The list Object to make a string from
|
||||||
*/
|
*/
|
||||||
int stringList(char* dest, const Object* obj)
|
void stringList(struct string* s, const Object* obj)
|
||||||
{
|
{
|
||||||
const char* initial = dest;
|
s->cursor += sprintf(s->cursor, "(");
|
||||||
|
|
||||||
dest += sprintf(dest, "(");
|
|
||||||
|
|
||||||
FOR_POINTER_IN_LIST(obj) {
|
FOR_POINTER_IN_LIST(obj) {
|
||||||
char tok[256] = "";
|
s->cursor += sprintf(s->cursor, " ");
|
||||||
stringObj(tok, POINTER);
|
stringNObj(s, POINTER);
|
||||||
dest += sprintf(dest, " %s", tok);
|
inflate(s, 0);
|
||||||
}
|
}
|
||||||
dest += sprintf(dest, " )");
|
s->cursor += sprintf(s->cursor, " )");
|
||||||
return dest - initial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a string from a given struct Object
|
* Creates a string from a given struct Object
|
||||||
* Blocks out with curly braces
|
* Blocks out with curly braces
|
||||||
*/
|
*/
|
||||||
int stringStruct(char* dest, const Object* obj)
|
void stringStruct(struct string* s, const Object* obj)
|
||||||
{
|
{
|
||||||
struct StructObject* so = obj->structObject;
|
struct StructObject* so = obj->structObject;
|
||||||
const char* initial = dest;
|
s->cursor += sprintf(s->cursor, "{");
|
||||||
dest += sprintf(dest, "{");
|
|
||||||
|
|
||||||
struct StructDef* def = getStructAt(so->definition);
|
struct StructDef* def = getStructAt(so->definition);
|
||||||
for (int i = 0; i < def->fieldCount; i++) {
|
for (int i = 0; i < def->fieldCount; i++) {
|
||||||
dest += sprintf(dest, " %s: ", def->names[i]);
|
s->cursor += sprintf(s->cursor, " %s: ", def->names[i]);
|
||||||
int isString = so->fields[i].type == TYPE_STRING;
|
int isString = so->fields[i].type == TYPE_STRING;
|
||||||
if (isString) {
|
if (isString) {
|
||||||
dest += sprintf(dest, "\"");
|
s->cursor += sprintf(s->cursor, "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
char tok[90] = "";
|
stringNObj(s, &so->fields[i]);
|
||||||
stringObj(tok, &so->fields[i]);
|
|
||||||
dest += sprintf(dest, "%s", tok);
|
|
||||||
|
|
||||||
if (isString) {
|
if (isString) {
|
||||||
dest += sprintf(dest, "\"");
|
s->cursor += sprintf(s->cursor, "\"");
|
||||||
}
|
}
|
||||||
dest += sprintf(dest, ",");
|
s->cursor += sprintf(s->cursor, ",");
|
||||||
}
|
}
|
||||||
dest--;
|
s->cursor--;
|
||||||
dest += sprintf(dest, " }");
|
s->cursor += sprintf(s->cursor, " }");
|
||||||
return dest - initial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a string from a given Object
|
* Creates a string from a given Object
|
||||||
* Returns NULL if either param is NULL
|
* Returns NULL if either param is NULL
|
||||||
|
@ -214,96 +231,90 @@ int stringStruct(char* dest, const Object* obj)
|
||||||
* @param dest The string to copy the list text into
|
* @param dest The string to copy the list text into
|
||||||
* @param obj The list Object to make a string from
|
* @param obj The list Object to make a string from
|
||||||
*/
|
*/
|
||||||
#ifdef STANDALONE
|
int stringNObj(struct string* s, const Object* obj)
|
||||||
#define stringf(_dest, _len, _format, args...) sprintf(_dest, _format, ## args)
|
|
||||||
#else
|
|
||||||
#define stringf(_dest, _len, _format, args...) snprintf(_dest, _len, _format, ## args)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int stringNObj(char* dest, const Object* obj, const size_t len)
|
|
||||||
{
|
{
|
||||||
const char* initial = dest;
|
inflate(s, 16);
|
||||||
|
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
case TYPE_NUMBER:
|
case TYPE_NUMBER:
|
||||||
dest += stringf(dest, len, "%d", obj->number);
|
s->cursor += sprintf(s->cursor, "%d", obj->number);
|
||||||
break;
|
break;
|
||||||
case TYPE_BOOL:
|
case TYPE_BOOL:
|
||||||
dest += stringf(dest, len, "%s", obj->number ? "T" : "F");
|
s->cursor += sprintf(s->cursor, "%s", obj->number ? "T" : "F");
|
||||||
break;
|
break;
|
||||||
case TYPE_STRING:
|
case TYPE_STRING: {
|
||||||
dest += stringf(dest, len, "%s", obj->string);
|
size_t stringLen = strlen(obj->string);
|
||||||
|
inflate(s, stringLen);
|
||||||
|
s->cursor += sprintf(s->cursor, "%s", obj->string);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case TYPE_SYMBOL:
|
case TYPE_SYMBOL:
|
||||||
dest += stringf(dest, len, "`%s`", obj->string);
|
s->cursor += sprintf(s->cursor, "`%s`", obj->string);
|
||||||
break;
|
break;
|
||||||
case TYPE_STRUCT:
|
case TYPE_STRUCT:
|
||||||
//snprintf(dest, len, "{%s}", obj->structObject->definition->names[0]);
|
stringStruct(s, obj);
|
||||||
dest += stringStruct(dest, obj);
|
|
||||||
break;
|
break;
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
case TYPE_SLIST:
|
case TYPE_SLIST:
|
||||||
dest += stringList(dest, obj);
|
stringList(s, obj);
|
||||||
break;
|
break;
|
||||||
case TYPE_ERROR: {
|
case TYPE_ERROR: {
|
||||||
int code = getErrorCode(*obj);
|
int code = getErrorCode(*obj);
|
||||||
#ifdef SIMPLE_ERRORS
|
#ifdef SIMPLE_ERRORS
|
||||||
dest += stringf(dest, len, "E[%d]", (int)code);
|
s->cursor += sprintf(s->cursor, "E[%d]", (int)code);
|
||||||
#else
|
#else
|
||||||
|
inflate(s, 128);
|
||||||
if (obj->error->context && obj->error->context[0] != '\0') {
|
if (obj->error->context && obj->error->context[0] != '\0') {
|
||||||
dest += stringf(dest, len, "%s: %s", errorText[code],
|
s->cursor += sprintf(s->cursor, "%s: %s", errorText[code],
|
||||||
obj->error->context);
|
obj->error->context);
|
||||||
} else if (code >= 0 && code <= INDEX_PAST_END) {
|
} else if (code >= 0 && code <= INDEX_PAST_END) {
|
||||||
dest += stringf(dest, len, "%s", errorText[code]);
|
s->cursor += sprintf(s->cursor, "%s", errorText[code]);
|
||||||
} else {
|
} else {
|
||||||
dest += stringf(dest, len, "BROKEN ERROR CODE: %d", code);
|
s->cursor += sprintf(s->cursor, "BROKEN ERROR CODE: %d", code);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_FUNC:
|
case TYPE_FUNC:
|
||||||
dest += stringf(dest, len, "F%d", obj->number);
|
s->cursor += sprintf(s->cursor, "F%d", obj->number);
|
||||||
break;
|
break;
|
||||||
case TYPE_LAMBDA: {
|
case TYPE_LAMBDA: {
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dest += stringf(dest, len, "\\x%d", obj->number);
|
s->cursor += sprintf(s->cursor, len, "\\x%d", obj->number);
|
||||||
#endif
|
#endif
|
||||||
dest += stringNObj(dest, &obj->lambda->params, len);
|
stringNObj(s, &obj->lambda->params);
|
||||||
dest += sprintf(dest, " -> ");
|
s->cursor += sprintf(s->cursor, " -> ");
|
||||||
dest += stringNObj(dest, &obj->lambda->body, len);
|
stringNObj(s, &obj->lambda->body);
|
||||||
dest += sprintf(dest, ">");
|
s->cursor += sprintf(s->cursor, ">");
|
||||||
#else
|
#else
|
||||||
dest += stringf(dest, len, "\\x%d", obj->number);
|
s->cursor += sprintf(s->cursor, len, "\\x%d", obj->number);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_OTHER:
|
case TYPE_OTHER:
|
||||||
dest += stringf(dest, len, "%p", obj->other->data);
|
s->cursor += sprintf(s->cursor, "%p", obj->other->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidType(*obj)) {
|
if (!isValidType(*obj)) {
|
||||||
dest += stringf(dest, len, "BAD_TYPE(%d) X%d", obj->type, obj->number);
|
s->cursor += sprintf(s->cursor, "BAD_TYPE(%d) X%d", obj->type, obj->number);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest - initial;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int stringObj(char* dest, const Object* obj)
|
char* stringObj(const Object* obj, size_t* length)
|
||||||
{
|
{
|
||||||
return stringNObj(dest, obj, RESULT_LENGTH);
|
char* alloc = malloc(8);
|
||||||
}
|
struct string s = {
|
||||||
|
.allocPoint = alloc,
|
||||||
/**
|
.cursor = alloc,
|
||||||
* Prints a given Object only if the DEBUG flag is set
|
.capacity = 8,
|
||||||
* @param obj The Object to debug
|
};
|
||||||
*/
|
s.allocPoint[0] = '\0';
|
||||||
void debugObj(const Object* obj)
|
stringNObj(&s, obj);
|
||||||
{
|
*length = s.cursor - s.allocPoint;
|
||||||
#ifdef DEBUG
|
return s.allocPoint;
|
||||||
printObj(obj);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(STANDALONE)
|
#if defined(DEBUG) || defined(STANDALONE)
|
||||||
|
@ -341,33 +352,28 @@ void printType(const Object* obj)
|
||||||
|
|
||||||
void _printObj(const Object* obj, int newline)
|
void _printObj(const Object* obj, int newline)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
|
||||||
printType(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
printf(newline ? "\n" : "");
|
printf(newline ? "\n" : "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char temp[1024] = "";
|
size_t length;
|
||||||
stringNObj(temp, obj, 1024);
|
char* temp = stringObj(obj, &length);
|
||||||
if (newline) {
|
if (newline) {
|
||||||
printf("%s\n", temp);
|
printf("%s\n", temp);
|
||||||
if (obj->type == TYPE_ERROR) {
|
if (obj->type == TYPE_ERROR) {
|
||||||
if (obj->error && obj->error->plContext) {
|
if (obj->error && obj->error->plContext) {
|
||||||
printf("%s\n", obj->error->plContext->text);
|
printf("%s\n", obj->error->plContext->text);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("%s", temp);
|
printf("%s", temp);
|
||||||
}
|
}
|
||||||
|
free(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the given Object and a newline.
|
* Prints the given Object and a newline.
|
||||||
* Uses stringObj() to create the printed string
|
* Uses stringObj() to create the printed string
|
||||||
* If the DEBUG flag is set, the Object's type will be printed first
|
|
||||||
* @param obj The Object to print
|
* @param obj The Object to print
|
||||||
*/
|
*/
|
||||||
inline void printObj(const Object* obj)
|
inline void printObj(const Object* obj)
|
||||||
|
|
|
@ -128,9 +128,13 @@ struct Other {
|
||||||
void* data;
|
void* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
int stringNObj(char* dest, const Object* obj, size_t len);
|
struct string {
|
||||||
|
char* allocPoint;
|
||||||
|
char* cursor;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
int stringObj(char* dest, const Object* obj);
|
char* stringObj(const Object* obj, size_t* length);
|
||||||
|
|
||||||
void printType(const Object* obj);
|
void printType(const Object* obj);
|
||||||
|
|
||||||
|
|
|
@ -607,8 +607,8 @@ void repl(struct Environment* env)
|
||||||
}
|
}
|
||||||
add_history(buf);
|
add_history(buf);
|
||||||
Object o = parseEval(buf, env);
|
Object o = parseEval(buf, env);
|
||||||
char output[1024];
|
size_t length;
|
||||||
stringNObj(output, &o, 1024);
|
char *output = stringObj(&o, &length);
|
||||||
printColored(output);
|
printColored(output);
|
||||||
printf("[0m\n");
|
printf("[0m\n");
|
||||||
cleanObject(&o);
|
cleanObject(&o);
|
||||||
|
|
14
src/plfunc.c
14
src/plfunc.c
|
@ -8,7 +8,7 @@ Object typeCheck(const char* funcName, Object* params, int length,
|
||||||
{
|
{
|
||||||
*failed = 1;
|
*failed = 1;
|
||||||
if ((typeLength - 1) > length) {
|
if ((typeLength - 1) > length) {
|
||||||
return errorObject(NOT_ENOUGH_ARGUMENTS);
|
return errorWithContext(NOT_ENOUGH_ARGUMENTS, funcName);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < typeLength - 1; i++) {
|
for (int i = 0; i < typeLength - 1; i++) {
|
||||||
if (typeChecks[i] && !typeChecks[i](params[i])) { // TODO: Use pl func name instead of C function name.
|
if (typeChecks[i] && !typeChecks[i](params[i])) { // TODO: Use pl func name instead of C function name.
|
||||||
|
@ -235,16 +235,18 @@ Object _catObjects(Object obj1, Object obj2, struct Environment* env)
|
||||||
Object evalObj1 = eval(&obj1, env);
|
Object evalObj1 = eval(&obj1, env);
|
||||||
Object evalObj2 = eval(&obj2, env);
|
Object evalObj2 = eval(&obj2, env);
|
||||||
|
|
||||||
char str1[CAT_MAX] = "";
|
size_t length1;
|
||||||
char str2[CAT_MAX] = "";
|
size_t length2;
|
||||||
int length = stringObj(str1, &evalObj1);
|
char* str1 = stringObj(&evalObj1, &length1);
|
||||||
length += stringObj(str2, &evalObj2);
|
char* str2 = stringObj(&evalObj2, &length2);
|
||||||
|
|
||||||
cleanObject(&evalObj1);
|
cleanObject(&evalObj1);
|
||||||
cleanObject(&evalObj2);
|
cleanObject(&evalObj2);
|
||||||
|
|
||||||
Object o = withLen(length, TYPE_STRING);
|
Object o = withLen(length1 + length2, TYPE_STRING);
|
||||||
sprintf(o.string, "%s%s", str1, str2);
|
sprintf(o.string, "%s%s", str1, str2);
|
||||||
|
free(str1);
|
||||||
|
free(str2);
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,8 @@ answer_to_connection(void* cls, struct MHD_Connection* connection,
|
||||||
Object queryParams = listObject();
|
Object queryParams = listObject();
|
||||||
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, add_query_param, &queryParams);
|
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, add_query_param, &queryParams);
|
||||||
|
|
||||||
Object res = numberObject(1010);//structObject(requestDefinition);
|
Object res = structObject(requestDefinition);
|
||||||
//res.structObject->fields[0] = queryParams;
|
res.structObject->fields[0] = queryParams;
|
||||||
Object route = cloneObject(routes[i].routeAction);
|
Object route = cloneObject(routes[i].routeAction);
|
||||||
|
|
||||||
Object result = listEvalLambda(&route, &res, 2, routes[i].env);
|
Object result = listEvalLambda(&route, &res, 2, routes[i].env);
|
||||||
|
|
Loading…
Reference in New Issue