diff --git a/src/env.c b/src/env.c index c4df943..a5be7c4 100644 --- a/src/env.c +++ b/src/env.c @@ -215,8 +215,7 @@ struct helpText { int currentHelp = 0; struct helpText helpTexts[100]; -#define pfn(_func) buildFuncSym(_func ## Symbol, &(_func), _func ## Doc, NULL) -#define pf(_name, _func) buildFuncSym(_name, &(_func), _func ## Doc, _func ## Tests, array_length(_func ## Tests)) +#define pf(_func) buildFuncSym(_func ## Symbol, &(_func), _func ## Doc, _func ## Tests, array_length(_func ## Tests)) /// For any instances (e.g. segfault recovery) where defaultEnv() may be called /// multiple times. @@ -282,11 +281,12 @@ void printColored(const char* code) } } -fn(help, +fn(help, "?", "Gets a string with help text for the given function.\n" "For example:\n" " (? islist) => \"(islist (1 2 3)) => T\"" -) { +) +{ const char* symbol; if (!length || !params[0].string || params[0].string[0] == '\0') { symbol = "?"; @@ -316,7 +316,9 @@ fn(help, return nullTerminated("Help not found!"); } -fnn(segfault, "seg", "Induces a segfault.") +fn(segfault, "seg", + "Induces a segfault." +) { int* p = NULL; return numberObject(*p); @@ -403,41 +405,40 @@ struct Environment defaultEnv() {"<", &lessThan}, {"&", &and}, {"|", &or}, - pf("cat", catObjects), - pf("fil", filter), - pf("len", len), - pf("ap", append), - pf("pre", prepend), - pf("reduce", reduce), - pf("at", at), - pf("rest", rest), - pf("chat", charAt), + pf(catObjects), + pf(filter), + pf(len), + pf(append), + pf(prepend), + pf(reduce), + pf(at), + pf(rest), + pf(charAt), #ifndef LOW_MEM - pf("rev", reverse), + pf(reverse), #endif - pf("isnum", isNum), - pf("islist", isList), - pf("isstr", isString), - pf("iserr", isErr), - pf("char", charVal), - pf("eval", parseEvalO), - pf("poss", possessive), + pf(isNum), + pf(isList), + pf(isString), + pf(isErr), + pf(charVal), + pf(parseEvalO), + pf(possessive), #ifdef WEBSERVER - pf("get", addGetRoute), - pf("post", addPostRoute), - pf("serve", startServer), + pf(addGetRoute), + pf(addPostRoute), + pf(startServer), #endif #ifdef STANDALONE - pf("seg", segfault), - //pfn(segfault), - pf("prn", print), - pf("ch", numToChar), - pf("penv", printEnvO), - pf("sys", systemCall), - pf("loadfile", loadFile), - pf("inp", takeInput), - pf("rf", readFileToObject), - pf("?", help) + pf(segfault), + pf(print), + pf(numToChar), + pf(printEnvO), + pf(systemCall), + pf(loadFile), + pf(takeInput), + pf(readFileToObject), + pf(help) #endif }; diff --git a/src/pebblisp.h b/src/pebblisp.h index c734775..4bb4ac7 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -12,20 +12,21 @@ #define UNPACK(...) __VA_ARGS__ -#define fn(_name, _docs, ...) \ +#define fnn(_name, _docs, ...) \ static const char * const _name ## Doc = _docs; \ 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) // GCC warns without the attribute, even when typeChecks are used -#define tfn(_name, _type, _docs, ...) \ +#define tfn(_name, _symbol, _type, _docs, ...) \ __attribute__((unused)) static int (*_name ## TypeChecks[])(Object) = UNPACK _type; \ -fn(_name, _docs, __VA_ARGS__) - -#define fnn(_name, _symbol, _docs, ...) \ static const char * const _name ## Symbol = _symbol; \ -fn(_name, _docs, __VA_ARGS__) +fnn(_name, _docs, __VA_ARGS__) + +#define fn(_name, _symbol, _docs, ...) \ +static const char * const _name ## Symbol = _symbol; \ +fnn(_name, _docs, __VA_ARGS__) struct Slice { const char* text; diff --git a/src/plfunc.h b/src/plfunc.h index e200530..a621a92 100644 --- a/src/plfunc.h +++ b/src/plfunc.h @@ -28,32 +28,32 @@ BASIC_OP(or); #undef BASIC_OP -tfn(catObjects, +tfn(catObjects, "cat", ({ NULL, isStringy }), "Concatenate string representations of the given objects.", "(cat \"Stuff: \" (1 2 3))", "Stuff: ( 1 2 3 )", ); -tfn(filter, +tfn(filter, "fil", ({ isFuncy, isListy, isListy }), "Filter a list based on the given condition.", "(fil (fn (a) (< 50 a)) (25 60 100))", "( 60 100 )", "(fil (fn (a) (< 0 (len a))) ( () (1) (1 2) () ))", "( ( 1 ) ( 1 2 ) )", ); -tfn(append, +tfn(append, "ap", ({ isListy, NULL, isListy }), "Append the given element. Creates a new list.", "(ap (1 2) 3)", "( 1 2 3 )", ); -tfn(prepend, +tfn(prepend, "pre", ({ isListy, NULL, isListy }), "Prepend the given element. Creates a new list", "(pre (2 3) 1)", "( 1 2 3 )", ); -tfn(len, +tfn(len, "len", ({ isListy, isNumber }), "Returns the length of the given list, or an error if the expression is not a list.", "(len (2 3))", "2", @@ -61,7 +61,7 @@ tfn(len, "(len \"string\")", "BAD_PARAMS_ON: len", ); -tfn(reduce, +tfn(reduce, "reduce", ({ NULL, isFuncy, NULL, NULL }), "Performs a simple reduction. Does not currently work with lambdas.\n" "Takes three arguments:\n" @@ -72,7 +72,7 @@ tfn(reduce, "(reduce (1 2 3) + 0)", "6", ); -tfn(at, +tfn(at, "at", ({ isNumber, isListy, NULL }), "Get item at the given index in the given list.", "(at 1 (1 2 3))", "2", @@ -80,7 +80,7 @@ tfn(at, "(at 99 \"string\")", "BAD_PARAMS_ON: at", ); -tfn(rest, +tfn(rest, "rest", ({ isListy, isListy }), "Get the tail of a list. All but the first element.", "(rest (1 2 3))", "( 2 3 )", @@ -88,14 +88,14 @@ tfn(rest, "(rest \"string\")", "BAD_PARAMS_ON: rest", ); -tfn(reverse, +tfn(reverse, "rev", ({ isListy, isListy }), "Reverse a list.", "(rev (1 2 3))", "( 3 2 1 )", "(rev \"string\")", "BAD_PARAMS_ON: reverse", ); -tfn(isNum, +tfn(isNum, "isnum", ({ NULL, isBool }), "Returns `T` only if the argument evaluates to a number.", "(isnum 1)", "T", @@ -104,7 +104,7 @@ tfn(isNum, "(isnum \"Hello\")", "F", ); -tfn(isList, +tfn(isList, "islist", ({ NULL, isBool }), "Returns `T` only if the argument is a list.", "(islist (1 2 3))", "T", @@ -112,7 +112,7 @@ tfn(isList, "(islist \"Stringy\")", "F", ); -tfn(isString, +tfn(isString, "isstr", ({ NULL, isBool }), "Returns `T` only if the argument is a string.", "(isstr \"Heyo\")", "T", @@ -121,21 +121,21 @@ tfn(isString, "(isstr 10)", "F", ); -tfn(isErr, +tfn(isErr, "iserr", ({ NULL, isBool }), "Check if the argument is an error.", "(iserr (at 10 ()))", "T", "(iserr 5)", "F", ); -tfn(charAt, - ({isStringy, isNumber, isStringy}), +tfn(charAt, "chat", + ({ isStringy, isNumber, isStringy }), "Get the char in the given string at the given index.", "(chat \"Hello\" 1)", "e", "(chat \"Hello\" 10)", "", ); -tfn(charVal, +tfn(charVal, "char", ({ isStringy, isNumber }), "Get the ascii integer representaton of the given character.", "(char \"h\")", "104", @@ -144,14 +144,14 @@ tfn(charVal, ); /// STRING/SLIST => ANY -fn(parseEvalO, +fn(parseEvalO, "eval", "Evaluate the given string or quoted list.", "(eval \"(1 2 3)\")", "( 1 2 3 )", "(eval '(+ 5 5))", "10", ); /// STRUCT, STRING => ANY -fn(possessive, +fn(possessive, "poss", "(struct Post (title body))\n" "(def p (Post \"TI\" \"BO\"))\n" "p's title => TI" @@ -159,25 +159,25 @@ fn(possessive, #ifdef STANDALONE -fn(print, "Prints the string representation of the given object to stdout."); +fn(print, "prn", "Prints the string representation of the given object to stdout."); -tfn(numToChar, +tfn(numToChar, "ch", ({ isNumber, isStringy }), "Gets a string containing the ascii character for the given number value.", "(ch 107)", "k", "(ch 0x21)", "!", ); -fn(printEnvO, "Prints out the current scoped environment."); +fn(printEnvO, "penv", "Prints out the current scoped environment."); -tfn(systemCall, +tfn(systemCall, "sys", ({ isStringy, isNumber }), "Opens a shell and runs the given command, returning 0 if successful.\n" "If the argument is not a string, returns 255.\n", "(sys \"echo yee > /dev/null\")", "0", ); -tfn(loadFile, +tfn(loadFile, "loadfile", ({ isStringy, NULL }), "Loads and parses the given file.\n" "Returns 0 if the file was loaded and parsed successfully. Otherwise 1.\n" @@ -189,13 +189,13 @@ tfn(loadFile, /// @code /// () => STRING /// STRING => STRING -fn(takeInput, +fn(takeInput, "inp", "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 \">> \"))` wait for input, but prompt the user with '>> '.\n" ); -tfn(readFileToObject, +tfn(readFileToObject, "rf", ({ isStringy, isStringy }), "Read a file into a string object." ); diff --git a/src/web.h b/src/web.h index 18bd8b9..ec715c2 100644 --- a/src/web.h +++ b/src/web.h @@ -1,13 +1,13 @@ #include "pebblisp.h" -fn(startServer, +fn(startServer, "serve", "(serve) => 0\n" "Starts a simple web server with routes that have been added using (get) and (post).\n" "Returns 0 if the server was successfully started, otherwise 1.\n" "Note: Not a blocking call! Calling (inp) is a simple way to keep the server open.\n" ); -fn(addGetRoute, +fn(addGetRoute, "get", "Adds a GET route at the given path with the given function.\n" " (get \"/\" (fn () (\"Hello, world!\")))\n" " (get \"/parampath\" (fn (req) (req's queryParams)))\n" @@ -15,7 +15,7 @@ fn(addGetRoute, "Also see: (serve)\n" ); -fn(addPostRoute, +fn(addPostRoute, "post", "Adds a POST route at the given path with the given function.\n" "Note: Can't do anything with POSTed data yet.\n" " (post \"/\" (fn () (\"Hello, world!\")))\n"