{"id":13782481,"url":"https://github.com/jondeaton/Lisp","last_synced_at":"2025-05-11T15:32:33.312Z","repository":{"id":67648546,"uuid":"101908856","full_name":"jondeaton/Lisp","owner":"jondeaton","description":"Lisp interpreter written in C","archived":false,"fork":false,"pushed_at":"2019-09-27T05:45:42.000Z","size":450,"stargazers_count":8,"open_issues_count":7,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-17T17:43:21.968Z","etag":null,"topics":["c","lisp"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jondeaton.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2017-08-30T17:18:55.000Z","updated_at":"2022-12-11T19:53:03.000Z","dependencies_parsed_at":"2023-04-19T14:24:52.318Z","dependency_job_id":null,"html_url":"https://github.com/jondeaton/Lisp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondeaton%2FLisp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondeaton%2FLisp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondeaton%2FLisp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondeaton%2FLisp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jondeaton","download_url":"https://codeload.github.com/jondeaton/Lisp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253588747,"owners_count":21932317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["c","lisp"],"created_at":"2024-08-03T18:01:37.815Z","updated_at":"2025-05-11T15:32:32.805Z","avatar_url":"https://github.com/jondeaton.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# Lisp Interpreter from C\n\nThis repository contains a Lisp interpreter written from scratch in pure C (c99).\nThe interpreter can be used to run Lisp programs saved in files, or from an\ninteractive shell. This Lisp interpreter showcases many features including\nvariable and function declaration, arithmetic operations,\nfirst class/lambda functions, closures, currying, recursive functions,\na mutable global interpreter environment, dynamic scoping, memory allocation\nand deterministic memory management without garbage collection.\n\nAlthough the interpreter and all of it's libraries are written in C, performance\nbenchmarking and some unit testing are done using\n[Google Benchmark](https://github.com/google/benchmark \"Google Benchmark\")\nand\n[Google Test](https://github.com/google/googletest \"Google Test\"),\nrespectively, which are both C++ libraries. If you want to build\nthe performance and unit testing binaries, you will need a C++ compiler.\n\n#### Example\n\nThe Lisp interpreter comes with a global environment which can be used to set values and then recal them later\n\n    \u003e (set 'x 6)\n    6\n    \u003e (set 'y 7)\n    7\n    \u003e (* x y)\n    42\n\n\nThis interpreter also supports the creation of closures from lambda functions with variable capture at declaraion time.\n\n    \u003e (set 'make-adder \n        (lambda (x) \n          (lambda (n) (+ x n))))\n    \u003cclosure:(x), 2 vars captured\u003e\n    \u003e (set 'add-2 (make-adder 2))\n    \u003cclosure:(n), 2 vars captured\u003e\n    \u003e (add-2 40)\n    42\n\nIn this example the `make-adder` function returns a closure with the value of `n` captured within the closure.\nRecursive functions may declared, such as this recursive definition of the factorial function:\n\n    \u003e (set 'factorial \n        (lambda (n)\n          (cond\n            ((= n 0) 1)\n            (t       (* n (factorial (- n 1)))))))\n    \u003e (factorial 6)\n    720\n\nrecursion may even be accomplished with anonymous functions via the Y-Combinator\n\n    \u003e (set 'Y\n       (lambda (r)\n        ((lambda (f) (f f))\n         (lambda (f) (r (lambda (x) ((f f) x)))))))\n    \u003e (set 'F\n       (lambda (g)\n        (lambda (n)\n         (cond \n          ((= n 0) 1)\n          (t       (* n (g (- n 1))))))))\n    \u003e ((Y F) 6)\n    720\n\n\n## Usage\nIf you would like to run this Lisp interpreter from the command line, you will have to\nbuild it from source using the CMake build system. To do so, you will need to have a C99 compiler,\nand the CMake build system. To build, issue the following two commands from with in the top-level directory\n\n    cmake .\n\n    make\n\nTo run the interactive shell (REPL) use the `lisp` executable.\nTo have matching parentheses hilighting, run `echo \"set blink-matching-paren on\" \u003e\u003e ~/.inputrc`.\nYou can also run a Lisp script by adding it as an argument.\n\n   `./lisp my-program.lisp`\n\n## Dependencies\n1. C99\n2. Readline\n    - Ubuntu: `sudo apt-get install libreadline-dev`\n    - MacOS: `brew install readline`\n\n## Testing and Benchmarking\nIf you would like to check out my handiwork, a testing framework for the interpreter\nis also included and can be run with the `test-lisp` executable.\n\nFor performance benchmarking, we use the\n[Google Benchmark library](https://github.com/google/benchmark \"Google Benchmark\").\nTo use this part of the repository, you will need a C++ compiler (as this library\nis written in C++) and have installed the library as instructed.\n\n## Design\nTo understand in greater detail the design choices which were made in the creation of this interpreter\nyou may refer to `design.md`.\n\n## To do\nThe following \"to do\" list contains many things which I have accomplished in this project as well\nas things which I have not yet accomplished. Please cross one off!\n\n- ~~REPL prompt and re-prompt~~\n- ~~Correct parsing and un-parsing~~\n- ~~`eval` and `apply`~~\n- ~~Implement testing framework~~\n- ~~Seven primitives~~\n- ~~set primitive~~\n- ~~basic `lambda` functionality~~\n- ~~Error messages and stack trace~~\n- ~~Smart indentation in re-prompt'~~\n- ~~Use `readline` for interactive prompt~~\n- ~~Math library~~\n- ~~`env` primitive to print the environment~~\n- ~~memory management~~\n- ~~closures~~\n- ~~Use CList instead of CVector~~\n- ~~Lambda with zero arguments~~\n- ~~Closure partial application~~\n- ~~Empty expression is not invalid~~\n- ~~Signal handler in REPL (to exit gracefully with garbage collection)~~\n- ~~Abstract Lisp Interpreter and Garbage Collector into structure~~\n- ~~Allow for REPL to run from any file descriptor~~\n- ~~Proper error reporting on file reading and malloc failure~~\n- ~~Specify lisp history file~~\n- ~~Verbose logging functionality with CLI flag~~\n- ~~Exit on error during program execution~~\n- ~~Tests for proper error behavior~~\n- ~~Greater than and less than primitives~~\n- ~~lambda primitive instead of special case~~\n- ~~Fix the help/version printout~~\n- ~~Use tail recursion instead of loops where possible~~\n- ~~Fix bug with `car` and `cdr` of empty list, or end of list~~\n- ~~Enable testing framework to report which test is failing~~\n- ~~Fix self-referential environment setting~~\n- ~~Fix variable capture of overloaded parameter names~~\n- ~~Fix the way that unused variables are handled~~\n  - ~~`#define UNUSED __attribute__ ((unused))`~~\n- ~~Change the error logger to use `snptintf` instead of `sprintf`~~\n- ~~Rename the garbage collector to memory manager~~\n- ~~Nest structs inside one another where possible (GC, allocated CList)~~\n- ~~Use CVector instead of CList~~\n- ~~Y (U NO WORK) combinator tests~~\n- ~~Fix the way that errors are reported (no `return LOG_ERROR(...)`)~~\n- ~~Use flexible array member in lisp objects~~\n- Performance benchmarking\n- ~Pass full interpreter to primitives~\n- Lexical scoping\n- Allow circular references by keeping track of freed pointers\n- Use a single truth and nil tuple\n- `defmacro`\n- Avoid deleting large data structures during set with over-write\n- Garbage Collector\n- Lisp standard library\n- Dot notation / Variadic functions\n- Strings\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondeaton%2FLisp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjondeaton%2FLisp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondeaton%2FLisp/lists"}