diff --git a/.gitignore b/.gitignore index 9b8e5a4..4414b9f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ pl node_modules/ .idea/ +.clangd/ diff --git a/src/env.c b/src/env.c index 2b9c7a4..4f3ecb3 100644 --- a/src/env.c +++ b/src/env.c @@ -78,9 +78,12 @@ Object fetchFromEnvironment(const char* name, struct Environment* env) throw(DID_NOT_FIND_SYMBOL, "%s", name); } -void addToEnv(struct Environment* env, const char* name, const Object obj) +void setVar(struct Environment* env, const char* name, const Object obj, int recurse) { - struct StrippedObject* existing = fetch(name, env); + struct StrippedObject* existing = recurse + ? fetch(name, env) + : getFromTable(&env->table, name); + if (existing) { Object o = deStrip(*existing); cleanObject(&o); @@ -92,6 +95,16 @@ void addToEnv(struct Environment* env, const char* name, const Object obj) addToTable(&env->table, strdup(name), cloneObject(obj)); } +void addToEnv(struct Environment* env, const char* name, const Object obj) +{ + setVar(env, name, obj, 0); +} + +void setInEnv(struct Environment* env, const char* name, const Object obj) +{ + setVar(env, name, obj, 1); +} + /** * Build the local Environment for a given lambda * @param params List of symbol objects with the names of lambda params @@ -168,6 +181,7 @@ struct Environment defaultEnv() struct symFunc symFuncs[] = { pf(def), + pf(set), pf(add), pf(sub), pf(mul), diff --git a/src/env.h b/src/env.h index 31d5616..d2390c9 100644 --- a/src/env.h +++ b/src/env.h @@ -35,6 +35,8 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i void addToEnv(struct Environment* env, const char* name, Object obj); +void setInEnv(struct Environment* env, const char* name, Object obj); + void printEnv(struct Environment* env, int printPointers); void addFunc(const char* name, diff --git a/src/examples/forbble2.pbl b/src/examples/forbble2.pbl new file mode 100644 index 0000000..df9f5dd --- /dev/null +++ b/src/examples/forbble2.pbl @@ -0,0 +1,72 @@ +#!/usr/bin/pl + +; Initialize an empty stack +(def stack ()) + +(def stkadd (fn (a) + "Add the given value to the stack" + (set stack (pre stack a)) +)) + +(def pop (fn () + "Remove the top of the stack" + (if (> (len stack) 0) ( + (def top (at 0 stack)) + (set stack (rest stack)) + top + ) (prn "pop: STACK EMPTY")) +)) + +(def twop (fn (op) + "Apply the given operation to the top two stack elements" ( + (if (< (len stack) 2) () + (stkadd (op (pop) (pop))) + )))) + +(def swap (fn () ( + (def top (pop)) + (def bottom (pop)) + (stkadd top) + (stkadd bottom) +))) + +(def words (fn (text) ( + (split text " ") +))) + +(def pstack (fn () ( + (prnl (cat "Stack: " stack)) +))) + +(def e (fn (code) ( + (eval code) +))) + +(def loud-pop (fn () ( + (prnl (pop)) +))) + +(def fmap (fn (word) ( + ;(prnl (cat "fmap: " word)) + + (if (= "swap" word) (swap) + (if (= "??" word) (pstack) + (if (= "+" word) (twop +) + (if (= "-" word) (twop -) + (if (= "/" word) (twop /) + (if (= "*" word) (twop *) + (if (= "." word) (loud-pop) + (stkadd (eval word)) + ))))))) +))) + +(def repl (fn () ( + (def z (inp "plf:> ")) + (if (= z "q") () ( + (for-each fmap (words z)) + (prn nl) + (repl) + )) +))) + +(repl) diff --git a/src/examples/lib.pbl b/src/examples/lib.pbl index 3366354..b640885 100644 --- a/src/examples/lib.pbl +++ b/src/examples/lib.pbl @@ -1,7 +1,4 @@ #!/usr/bin/pl -; Print with newline -(def esc (ch 27)) - (def string (fn (a) (cat "" a))) (def nl (ch 10)) @@ -11,6 +8,25 @@ (prn (cat _txt nl)) ))) +(def _indexOf (fn (txt search) ( + (if (startsWith txt search) 0 + (+ 1 (_indexOf (substr 1 9999999 txt) search)) + ) +))) + +(def indexOf (fn (txt search) ( + (def i (_indexOf txt search)) + (if (> i (slen txt)) (- 0 1) i) +))) + +(def split (fn (txt splitter) + "Split a string at each instance of splitter" ( + (def i (indexOf txt splitter)) + (if (< i 0) (txt) + (pre (split (substr (+ 1 i) 9999999 txt) splitter) (substr 0 i txt)) + ) +))) + (def loadfile (fn (file-name) "Read and immediately evaluate the file with the given path." ( (eval (rf file-name)) @@ -52,7 +68,7 @@ (def for-each (fn (action list) "Apply the given action to each element in list." ( - (map f list) + (map action list) "" ))) diff --git a/src/examples/pebblisp.pbl b/src/examples/pebblisp.pbl index 617d4a3..78abc96 100644 --- a/src/examples/pebblisp.pbl +++ b/src/examples/pebblisp.pbl @@ -7,6 +7,8 @@ (def cyan "") (def white "") +(def esc (ch 27)) + (def bold "") (def reset "") (def ~ (env "HOME")) diff --git a/src/main.c b/src/main.c index 07b3763..d605ac7 100644 --- a/src/main.c +++ b/src/main.c @@ -254,8 +254,7 @@ int main(int argc, const char* argv[]) if (settings.configFile) { sprintf(config, "%s", settings.configFile); } else { - const char* const home = getenv("HOME"); - sprintf(config, "%s/.pebblisp.pbl", home); + sprintf(config, "%s/.pebblisp.pbl", getenv("HOME")); } if (readFile(config, &env) == 1 && settings.configFile) { fprintf(stderr, "Config file not found at %s\n", config); diff --git a/src/pebblisp.c b/src/pebblisp.c index 78f8418..74b6925 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -33,6 +33,18 @@ Object def(Object* params, unused int length, unused struct Environment* env) return cloneObject(params[0]); } +Object set(Object* params, unused int length, unused struct Environment* env) +{ + const char* name = params[0].string; + + Object finalValue = eval(¶ms[1], env); + + setInEnv(env, name, finalValue); + cleanObject(&finalValue); + + return cloneObject(params[0]); +} + /** * Add a struct to the environment with a given name and fields. * @@ -396,7 +408,8 @@ Result readSeq(struct Slice* tokens) tokens = r.slices; cleanObject(&r.obj); forceString = next->text[0] == '?' - || (strncmp(next->text, "def", 3) == 0); + || (strncmp(next->text, "def", 3) == 0) + || (strncmp(next->text, "setVar", 3) == 0); } } @@ -598,6 +611,14 @@ char* readFileToString(FILE* input) int c; int i = 1; // Skip refCount + if ((c = fgetc(input)) == '#') { + do { + c = fgetc(input); + } while (c != '\n' && c != EOF); + } else { + string[i++] = c; + } + while ((c = fgetc(input)) != EOF) { string[i] = c; i++; diff --git a/src/pebblisp.h b/src/pebblisp.h index 12b5973..2819aec 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -123,6 +123,12 @@ fn(def, "def", "(def x 10) x", "10", ); +fn(set, "set", + "Set the value for a variable.\n" + "Only defines a new variable if an existing one cannot be found.", + "(set x 10) x", "10", +); + tfn(structAccess, "poss", ({ expect(isStruct), anyType, anyType }), "Get the value of a struct's field",