{"id":13782694,"url":"https://github.com/Jaffe-/lispc","last_synced_at":"2025-05-11T16:30:59.812Z","repository":{"id":79222603,"uuid":"9788513","full_name":"Jaffe-/lispc","owner":"Jaffe-","description":"A simple Lisp interpreter in C","archived":false,"fork":false,"pushed_at":"2024-07-20T08:33:08.000Z","size":49,"stargazers_count":18,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-03T18:16:46.617Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/Jaffe-.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":"2013-05-01T09:03:09.000Z","updated_at":"2024-07-22T16:49:38.000Z","dependencies_parsed_at":"2024-04-24T12:59:48.273Z","dependency_job_id":"c23ef1da-7120-4b77-b507-a4d3a07a4e24","html_url":"https://github.com/Jaffe-/lispc","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/Jaffe-%2Flispc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaffe-%2Flispc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaffe-%2Flispc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaffe-%2Flispc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jaffe-","download_url":"https://codeload.github.com/Jaffe-/lispc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225068724,"owners_count":17416121,"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":[],"created_at":"2024-08-03T18:01:41.911Z","updated_at":"2024-11-17T17:31:56.743Z","avatar_url":"https://github.com/Jaffe-.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"lispc\n=====\n\nA simple Lisp interpreter written in C. It implements the most basic Lisp special forms (called operators here) as well as a small number of primitive procedures. It is lexically scoped and supports closures. \n\n## Building\n\nlispc should build out of the box on any system. Using gcc, simply do\n\n\u003e `gcc *.c -o lisp -std=c99`\n\nRunning the resulting executable will start the lispc interpreter. It does not parse files at the moment, and the REPL is very simple.\n\n## Language\n\nlispc is a minimalistic Lisp language. Expressions in lispc are either symbols, procedures, numbers or lists. Symbols are used as names in variable bindings, or can be used as identifiers for other purposes. A symbol evaluates to the value it is bound to. Numbers and procedures evaluate to themselves. List evaluation follows two basic rules: If the first element is a symbol and the symbol denotes one of the *operators*, evaluation rules for the particular operator is followed. If the first element does not denote one of the operators, the list expression is a function call. Every element in the list is evaluated, and the first element, if resulting in a procedure, is called with the rest of the elements as arguments.\n\nSome examples:\n\nNumbers evaluate to themselves:\n\n    LISP\u003e 1234\n    =\u003e 1234\n\n`def` is an operator, so the following list expression will be an operator call:\n\n    LISP\u003e (def k 2)\n    =\u003e K\n\nThe symbol `k` will after that call refer to the value 2:\n\n    LISP\u003e k\n    =\u003e 2\n\nA list where the first element is not an operator is a function call:\n\n    LISP\u003e (+ 1 (* 1 2) 3)\n    =\u003e 6\n\n### Operators\n\n#### `\\` (lambda)\n\n`(\\ (a1 a2 ...) exp)` constructs a function whose formal parameters are `a1`, `a2` and so on, and whose expression is `exp`. \n\nExample:\n\n    (\\ (x y z) (+ x y z))           ; a function which takes three arguments and sums them\n    ((\\ (x y z) (+ x y z)) 1 2 3)   ; create the described procedure and call it with arguments 1, 2 and 3\n\n#### `def` \n\n`(def a b)` introduces a new *variable binding* where the symbol `a` is bound tothe value `b`.\n\nExample:\n\n    (def a 5)                       ; define a to be 5\n    (def square (\\ (x) (* x x)))    ; set square to be the function which squares its argument\n\n#### `if` \n\n`(if test true-exp false-exp)` evaluates `test`. If the result is non-`NIL`, `true-exp` is evaluated. Otherwise, `false-exp` is evaluated. \n\nExample:\n\n    (if (= x 2) (+ x 1) 2)          ; evaluates (+ x 1) if x is equal to 2, or evaluates 2 if not\n\n#### `'` (quote)\n\n`(' exp)` simply evaluates to `exp`. The parser will convert expressions of the form `'x` to `(' x)`.\n\nExample:\n\n    LISP\u003e (' k)\n    =\u003e K\n    LISP\u003e 'k\n    =\u003e K\n\n#### `set!`\n\n`(set! a b)` changes the value what `a` refers to, to the value `b`. \n\n#### `let`\n\n`(let ((a1 b1) (a2 b2) ...) exp)` introduces *local bindings* of the symbol `a1` to the value `b1`, the symbol `a2` to the value `b2`, and so on. With these bindings, the `exp` expression is evaluated. The bindings only exist during the evaluation of `exp`. Already existant bindings outside the `let` scope will be shadowed by these bindings.\n\nExample:\n\n    (let ((x 2) (y 3))\n      (+ x y))                ; x and y are only bound in this expression\n\n#### `do` or `:` \n\n`(do exp1 exp2 ...)` evaluates the expressions `exp1`, `exp2`, ... in order, and uses the last evaluated value as its value.\n\nExample:\n\n    (do (print 'hi)\n      (print 'there) \n      1234)\n\nThis will print \"HI THERE\" on the screen, and the expression will evaluate to 1234.\n\n### Primitives\n\n### Generic functions\n\nThe standard library defines the functions `new-generic` and `implement` for using generic functions.\n\n`(new-generic name)` creates a new generic function called `name` and returns a procedure which can call it.\n\n`(implement name fn type)` defines a specific implementation of the generic function. `name` is the symbol of the generic function, `fn` is the implementing procedure, and `type` is a list or a symbol denoting the argument types the implementation handles. If `type` is a single symbol, the implementation is assumed to take a variable number of arguments, and every argument has to match this type. If `type` is a list, its items denote the argument types in order. \n\n#### Example\n\nThe function + might be useful to overload for certain types. The standard library implements + for integers as follows:\n\n    (def + (new-generic '+))\n    (implement '+ _+ 'integer)\n\nHere, `_+` denotes the built in primitive procedure for adding integers. The symbolic type argument makes this implementation accept a variable number of arguments, all of integer type. \n\nTo add a new implementation, for example for a type `matrix`, we can do\n\n    (implement '+ add-matrix '(matrix matrix))\n    \nHere, the type argument is a list of two elements, meaning that this implementation will take two arguments, both of type `matrix`. The function `add-matrix` must be a function taking at least two such arguments.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJaffe-%2Flispc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJaffe-%2Flispc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJaffe-%2Flispc/lists"}