{"id":15672830,"url":"https://github.com/siraben/eopl","last_synced_at":"2025-05-06T22:00:24.692Z","repository":{"id":111747561,"uuid":"172337643","full_name":"siraben/eopl","owner":"siraben","description":"Implementation of the languages from the EOPL textbook in Haskell and Standard ML.","archived":false,"fork":false,"pushed_at":"2019-12-22T07:07:41.000Z","size":48,"stargazers_count":15,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T03:23:03.736Z","etag":null,"topics":["eopl3","haskell","standard-ml"],"latest_commit_sha":null,"homepage":"","language":"Haskell","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/siraben.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,"publiccode":null,"codemeta":null}},"created_at":"2019-02-24T12:57:20.000Z","updated_at":"2023-07-14T19:18:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"2a7e8516-d695-4657-9e9e-b4ff4b67e395","html_url":"https://github.com/siraben/eopl","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/siraben%2Feopl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siraben%2Feopl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siraben%2Feopl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siraben%2Feopl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siraben","download_url":"https://codeload.github.com/siraben/eopl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252776573,"owners_count":21802467,"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":["eopl3","haskell","standard-ml"],"created_at":"2024-10-03T15:32:31.930Z","updated_at":"2025-05-06T22:00:24.625Z","avatar_url":"https://github.com/siraben.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Haskell and SML Implementations of the languages from EOPL\n\n```haskell\nWelcome to the LETREC interpreter. Control-d to exit.\nLETREC\u003e letrec fact(n) = if zero?(n) then 1 else *(n, (fact -(n,1))) in (fact 5)\n120\n```\n\nThis project aims to implement the languages found in the textbook\n[Essentials of Programming\nLanguages](https://mitpress.mit.edu/books/essentials-programming-languages),\nin Haskell.\n\n## Why?\nThe textbook implements the languages using Scheme, which is indeed a\nvery powerful functional programming language.  What about a Haskell\nversion?  This repository explores that, an intellectual exercise in\nimplementing various languages, which will later include ideas such as\nsuch as mutable state, exceptions, then object orientation and a\nmodule system, as EOPL does.\n\n## Implementation\n### Parser\nThe parser is implemented with monadic parser combinators.  This is\nwritten from scratch in Haskell.  Expressions are represented as\ninductive data types.  Since Haskell is pure, exceptions are\nimplemented with an `Exceptional` monad.\n\n### Interpreter\nThe interpreter is very simple.  In its current form it is an\nenvironment-passing interpreter, taking an expression, environment and\nreturning a `Result Val`, where `Result` is an alias for `Exceptional\nException`, where `Exceptional` is a type constructor of kind `* -\u003e\n*`.  This allows us to still signal errors during evaluation.\n\n## How to use\n### Haskell LETREC REPL\nRun `make` to build the Haskell REPL for the language `EXPLICIT-REFS`.\nThe Standard ML reference implementations can be run with SML/NJ, by\ntyping `use \"ref.sml\"` into the SML prompt.\n\n### Standard ML Functions\nThe most interesting function is probably `repf`, which accepts a\nfilename, parses it into the AST, runs `eval` over it and then uses\nthe pretty printer to display the result.  `runfile` reads the\nfilename, executes it but doesn't convert the final value into a\npretty printed version, which can be useful for debugging purposes.\n`parse_tree` accepts a filename and shows the parse tree for that\nfile.  Due to the way the grammar of the language is specified, you\nwill find that adding extra parens around expressions can dramatically\nchange its semantics.  `parse_tree` lets you see those invisible empty\nstring variable names that may pop up, for instance.\n\n## Program example (prime numbers with lazy streams)\n```text\n[ Comments are shown with square brackets (which cannot be nested) ]\n\nletrec\nstreamCar(s)  = car(s)\n[ We don't have thunks so pass a dummy value ]\nstreamCdr(s)  = (cdr(s) 44)\ntake(n)       = proc(s)\n                  if\n                    zero?(n)\n                  then\n                    emptylist\n                  else\n                    cons((streamCar s),\n                         ((take -(n,1)) (streamCdr s)))\n[ Some examples of stream operations. ]\nrepeat(n)     = cons_stream(n, (repeat n))\naddStreams(a) = proc(b) cons_stream(+(car(a),car(b)),\n                                    ((addStreams (streamCdr a)) (streamCdr b)))\n[ Modular arithmetic ]\nmod(x) =\n  proc(y)\n    let q = /(x,y) in\n      let a = *(y, q) in\n        -(x, a)\n\n[ Logical not ]\nnot(b) = if b then false else true\n\n[ Is n not divisible by b? ]\nndividesq(d) = proc(n) (not zero?(((mod n) d)))\nfilterStream(f) = proc(s)\n                    if\n                      (f car(s))\n                    then\n                      cons_stream(car(s),\n                                  ((filterStream f) (streamCdr s)))\n                    else\n                      ((filterStream f) (streamCdr s))\n\n[ The Sieve of Eratosthenes ]\nsieve(s) = cons_stream(car(s),\n                       (sieve ((filterStream (ndividesq car(s)))\n                                             (streamCdr s))))\n\n[ Generate integers starting from a number ]\nintegersFrom(z) = cons_stream(z, (integersFrom +(z,1)))\nin\n\n[ Get the first twenty prime numbers ]\n((take 20) (sieve (integersFrom 2)))\n```\n\n## Usage example\n### Standard ML\n```sml\n- parse_tree \"factorial.prog\";\nval it =\n  Letrec\n    ([\"fact\"],[\"n\"],\n     [If\n        (Zerop (Var \"n\"),Const 1,\n         Mult (Var \"n\",Call (Var \"fact\",Sub (Var \"n\",Const 1))))],\n     Call (Var \"fact\",Const 5)) : Expr\n- runfile \"factorial.prog\";\nval it = Num 120 : Val\n- repf \"streams.prog\";\nResult of evaluation: (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71)\nval it = () : unit\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiraben%2Feopl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiraben%2Feopl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiraben%2Feopl/lists"}