{"id":20256233,"url":"https://github.com/devcybiko/psil-fun","last_synced_at":"2026-06-03T22:31:18.949Z","repository":{"id":197051815,"uuid":"693858917","full_name":"devcybiko/psil-fun","owner":"devcybiko","description":null,"archived":false,"fork":false,"pushed_at":"2023-09-29T16:39:17.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-25T16:30:05.498Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devcybiko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-19T21:22:55.000Z","updated_at":"2023-09-28T16:58:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"5466324e-0a5b-42cd-9771-ed9d8048ffcf","html_url":"https://github.com/devcybiko/psil-fun","commit_stats":null,"previous_names":["devcybiko/psil-fun"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/devcybiko/psil-fun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fpsil-fun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fpsil-fun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fpsil-fun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fpsil-fun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devcybiko","download_url":"https://codeload.github.com/devcybiko/psil-fun/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fpsil-fun/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33883102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T10:45:57.163Z","updated_at":"2026-06-03T22:31:18.930Z","avatar_url":"https://github.com/devcybiko.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# psil-fun\n- a reverse-polish stack-based language loosely inspired by Lisp and Forth\n\n## Files\n- test.psil - example PSIL input file\n- psil.js - main code\n- psil_logger.js - logging \n- psil_ops.js - operators\n- psil_parse.js - parser\n- psil_stack.js - the stack class\n- psil_util.js - utilities\n\n## Running it\n- `./psil.js infile.psil --trace --debug --verbose`\n    - --trace = running commentary on the program sent to stderr\n    - --debug = debugging info sent to stdout\n    - --verbose = dumps the stack and symbol table on exit\n\n## Data Types\n- Number (any string that includes only digits and '.')\n- String (any non-number, plus literal strings surrounded by backticks (\\`) including whitespace and newlines\n- List - a grouping of objects surrounded by parentheses\n- Operator - any string that begins with non-alphanumeric characters\n    - some operators are already specified\n\n## Stack\n- each element (number, string, list) is pushed onto the stack\n- an operator may pull elements off the stack and perform operations on it\n    - optionally pushing new elements onto the stack\n\n## Symbol Table\n- there is one global symbol table holding variable names\n- use the assignment operator (\u003c-) to assign values to symbols\n- use the eval operator (\\$) to retrieve the value of symbols\n\n## Comments\n- a pound-sign `#` starts a single-line comment\n- all characters up to and including the newline are ignored\n- there is no 'multiline' comment\n- but you can use a multiline string and .pop it off the stack :/\n## Functions\n- Functions are just a list that is evaluated\n- Such a list can be assigned to a symbol and evaluated with `$$`\n```\n(.dup *) square \u003c-\n5 square$$\n```\n- Here, `(.dup *)` is a list containing the operator for duplicating the head of the stack, and then a multiplication.\n- `\u003c-` then assigns the list to the symbol `square`\n- Then, `5` is pushed onto the stack followed by the symbol `square`. \n- Finally the double-eval is called which first dereferences `square` - pushing `(.dup *)` onto the stack\n    - and then it immediately evaluates `(.dup *)`\n    - which duplicates `5` -\u003e `( 5 5 )`\n    - and invokes `*` which multiplies the two values -\u003e `(25)`\n\n## Operators\n- \"\\$\":  (a \\$) -\u003e (...) \"eval\" - pops the element and replaces it with the evaluation of the element\n    - if string - \"dereferences\" the string by replacing it with the value in the symbol table\n    - if list - executes each element in the list (pushing elements and evaluating operators)\n- \"\\$\\$\": (a \\$\\$) -\u003e (...) double eval - good for dereferencing a function and evaluating it\n- \"\u003c-\": ( b a \u003c- ) assign 'b' to the symbol 'a'\n    - note that we don't use the \"=\" operator\n    - this is to prevent confusion with the \"==\" operator\n\n- Binary Operators\n    - \"+\": ( b a + ) -\u003e (c) add b + a and push the result\n    - \"-\": subtraction\n    - \"*\": multiplication\n    - \"/\": division\n    - \"//\": integer division\n    - \"%\": modulus\n    - \"\u003e\": greater than\n    - \"\u003c\": less than\n    - \"\u003e=\": greater than or equal\n    - \"\u003c=\": less than or equal\n    - \"==\": equal to\n    - \"!=\": not equal to\n    - \"\u0026\u0026\": 'and'\n    - \"||\": 'or' \n\n- Unary operators\n    - \"!\": (a !) -\u003e (!a) - 'not'\n    - \"++\": (a ++) -\u003e () - increment a symbol's value\n    - \"--\": (a --) -\u003e () - decrement a symbol's value\n\n- List operators\n    - \"@\": index or lookup\n        - ((a A) (b B)) 'b' @) -\u003e (B) - treat 'list' as a dictionary and return the element whose 'car' == 'a'\n        - ((a b c) 1 @) -\u003e (b) - treat 'list' as an array and return the 'nth' element (zero-based)\n    - \".spread\": ((a b c) .spread) -\u003e (a b c) \n    - \".reduce\": (x (a b c) fn .reduce) -\u003e (result) - apply 'fn' to 'list' and accumulate the results\n    - \".map\": (a b c) fn -\u003e (A B C) - apply 'fn' to each element of 'list and push resulting list\n    - \".car\": ((a b c) .car) -\u003e (a)\n    - \".cdr\": ((a b c) .cdr) -\u003e ((b c))\n    - \".head\": (2 (a b c) .head) -\u003e (a b) - pulls the top 'n' elements from a list\n    - \".tail\": (2 (a b c) .tail) -\u003e (b c) - pulls the last 'n' elements from a list\n    - \".get\": (((a A) (b B) (c C)) 'a' .get) -\u003e (A) - treat list as dictionary and dereference\n    - \".nlist\": (a b c 2 .nlist) -\u003e (a (b c)) - group 'n' things together as a list\n\n- Stack Operators\n    - \".\": (a .) -\u003e (a a) - duplicate the head of the stack\n    - \".dup\": () =\u003e alias for '.'\n    - \".swap\": (a b c .swap) -\u003e (a c b) - swap the top elements of the stack\n    - \".pop\": (a b c .pop) -\u003e (a b) - pop an element off the stack and dispose of it\n\n- Conditional\n    - \"?:\": (a b c ?:) - if 'c' is true, push 'a', else push 'b'\n    - \".if\": (a b .if) -\u003e if 'b' is true, pushes the eval of a (a\\$)\n    - \".ifelse\": (a b c .ifelse) -\u003e if 'c' is true, push a\\$ else push b\\$\n\n- Loop\n    - \".each\": ((a b c) fn .each) -\u003e (A B C) - execute 'fn' against each of the elements of the list\n    - \".while\": (a .while) -\u003e (...) - eval 'a' then iterate if the resultant value on the stack is true\n\n- Other\n    - \"@@\": internal use only - sets the source code line number\n    - \"!!\": (a !!) -\u003e () - assert - if 'a' is false, die()\n    - \".str\": (3.14159 .str) -\u003e (\"3.14159\") - toString() operator\n    - \".int\": (\"123\" .int) -\u003e (123) - int() operator\n    - \".print\": (a .print) -\u003e () - print the head of the stack to stdout\n    - \".peek\": () =\u003e (a .peek) -\u003e (a) - print the head of the stack but don't pop it\n    - \".exit\": exit the program without debug\n    - \".die\": exit the program and dump the symbol table and stack\n\n- File I/O:\n    - \".import\": ('fname.psil' .import) -\u003e (...) - read the fname, parse it, and evaluate it\n    - \".export\": (list 'fname.psil' .export) -\u003e () - write the list to 'fname'\n    - \".read\": ('fname' .read) -\u003e (\"...\") - reads the file as a string and pushes it to the stack\n    - \".write\": (string 'fname' .write) -\u003e () - writes the 'string' to 'fname'\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevcybiko%2Fpsil-fun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevcybiko%2Fpsil-fun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevcybiko%2Fpsil-fun/lists"}