{"id":17779537,"url":"https://github.com/ymyzk/lambda-dti","last_synced_at":"2025-07-24T14:14:17.742Z","repository":{"id":42370899,"uuid":"152847684","full_name":"ymyzk/lambda-dti","owner":"ymyzk","description":"Interpreter of the ITGL with dynamic type inference","archived":false,"fork":false,"pushed_at":"2025-02-24T10:23:18.000Z","size":225,"stargazers_count":22,"open_issues_count":1,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-12T23:41:24.528Z","etag":null,"topics":["dune","functional-programming","gradual-typing","hindley-milner","interpreter","ocaml","repl","type-inferece"],"latest_commit_sha":null,"homepage":"https://dl.acm.org/do/10.1145/3291628/full/","language":"OCaml","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/ymyzk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["ymyzk"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2018-10-13T07:38:43.000Z","updated_at":"2025-02-26T09:18:04.000Z","dependencies_parsed_at":"2025-02-18T12:32:05.030Z","dependency_job_id":"d1808eab-77cc-40e9-a939-3a93288722e3","html_url":"https://github.com/ymyzk/lambda-dti","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/ymyzk/lambda-dti","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymyzk%2Flambda-dti","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymyzk%2Flambda-dti/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymyzk%2Flambda-dti/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymyzk%2Flambda-dti/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ymyzk","download_url":"https://codeload.github.com/ymyzk/lambda-dti/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymyzk%2Flambda-dti/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266854688,"owners_count":23995488,"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","status":"online","status_checked_at":"2025-07-24T02:00:09.469Z","response_time":99,"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":["dune","functional-programming","gradual-typing","hindley-milner","interpreter","ocaml","repl","type-inferece"],"created_at":"2024-10-27T01:04:29.662Z","updated_at":"2025-07-24T14:14:17.714Z","avatar_url":"https://github.com/ymyzk.png","language":"OCaml","funding_links":["https://github.com/sponsors/ymyzk"],"categories":[],"sub_categories":[],"readme":"# lambda-dti\n\n[![CI](https://github.com/ymyzk/lambda-dti/actions/workflows/ci.yml/badge.svg)](https://github.com/ymyzk/lambda-dti/actions/workflows/ci.yml)\n\n**lambda-dti** is an interpreter of the implicitly typed gradual language (ITGL) which uses **dynamic type inference** for evaluating programs.\nThis implementation consists of:\n\n- Garcia and Cimini's type inference algorithm;\n- a cast-inserting translator from the ITGL to the blame calculus;\n- an evaluator of the blame calculus with dynamic type inference; and\n- some extensions (recursion, operators, and libraries) to the ITGL.\n\nThis is the artifact of the following paper in POPL 2019.\n\n- Yusuke Miyazaki, Taro Sekiyama, and Atsushi Igarashi. [Dynamic Type Inference for Gradual Hindley–Milner Typing](https://doi.org/10.1145/3290331). POPL 2019.\n\n## Requirements\n- opam 2.0.0+\n- OCaml 4.03.0+\n- Dune 2.0.0+ (formerly known as Jbuilder)\n- Menhir\n- OUnit 2 (optional for running unit tests)\n- [rlwrap](https://github.com/hanslub42/rlwrap) (optional for line editing and input history)\n\n## Getting started\n### A. Building from source\n```console\ndune build\n./_build/default/bin/main.exe\n```\nRun `$ ./_build/default/bin/main.exe --help` for command line options.\n\n(Optional) Run the following command to install the application:\n```\n$ dune install\n$ ldti\n```\n\n### B. Running a Docker image\nDocker images are available on [GitHub](https://github.com/ymyzk/lambda-dti/pkgs/container/lambda-dti).\n\n```console\ndocker run -it --rm ghcr.io/ymyzk/lambda-dti:latest\n```\n\n### C. Running a virtual machine\nPlease see [HOW_TO_USE_ARTIFACT.md](./HOW_TO_USE_ARTIFACT.md) for details.\nThe virtual machine image contains [lambda-dti v2.1](https://github.com/ymyzk/lambda-dti/tree/v2.1).\n\n## Tips\n### Running tests\n```console\ndune runtest\n```\n\n### Debug mode\nBy enabling the debug mode, our interpreter show various messages to stderr.\n```console\nldti -d\n```\n\n### Non-interactive mode\nYou can specify a file as a command line argument. Our interpreter executes the programs in the file then exits.\n```console\nldti ./sample.ldti\n```\n\n### Line editing\nYou may want to use rlwrap for line editing and input history.\n```console\nrlwrap ldti\n```\n\n## Syntax\n### Top-level\n- Let declaration: `let x ... = e;;`\n- Recursion declaration: `let rec f x ... = e;;`\n- Expression: `e;;`\n\n### Expressions `e`\n- Variables: lowercase alphabet followed by lowercase alphabets, numbers, `_`, or `'`\n- Constants:\n  - Integers: `0`, `1`, `2`, ...\n  - Booleans: `true`, `false`\n  - Unit: `()`\n- Unary operators for integers: `+`,  `-`\n- Binary operators (from higher precedence to lower precedence):\n  - Integer multiplication, division, remainder (left): `*`, `/`, `mod`\n  - Integer addition, subtraction (left): `+`, `-`\n  - Integer comparators (left): `=`, `\u003c\u003e`, `\u003c`, `\u003c=`, `\u003e`, `\u003e=`\n  - Boolean and (right): `\u0026\u0026`\n  - Boolean or (right): `||`\n- Abstraction:\n  - Simple: `fun x -\u003e e`\n  - Multiple parameters: `fun x y z ... -\u003e e`\n  - With type annotations: `fun (x: U1) y (z: U3) ...: U -\u003e e`\n- Application: `e1 e2`\n- Let expression:\n  - Simple: `let x = e1 in e2`\n  - Multiple parameters: `let x y z ... = e1 in e2`\n  - With type annotations: `let (x:U1) y (z: U3) ... : U ... = e1 in e2`\n- Recursion (requires at least one parameter):\n  - Simple: `let rec f x = e1 in e2`\n  - Multiple parameters: `let rec f x y z ... = e1 in e2`\n  - With type annotations: `let rec f (x: U1) y (z: U3) ... : U = e1 in e2`\n- If-then-else expression: `if e1 then e2 else e3`\n- Sequence of expressions: `e1; e2`\n- Type ascription: `(e : U)`\n\n### Types `U`\n- Dynamic type: `?`\n- Base types: `bool`, `int`, and `unit`\n- Function type: `U -\u003e U`\n- Type variables: `'a`, `'b`, ...\n\n### Comments\n- Simple: `(* comments *)`\n- Nested comments: `(* leave comments here (* nested comments are also supported *) *)`\n\n## Standard library\nSome useful functions and values are available:\n```\n# is_bool;;\n- : ? -\u003e bool = \u003cfun\u003e\n# is_int;;\n- : ? -\u003e bool = \u003cfun\u003e\n# is_unit;;\n- : ? -\u003e bool = \u003cfun\u003e\n# is_fun;;\n- : ? -\u003e bool = \u003cfun\u003e\n\n# succ;;\n- : int -\u003e int = \u003cfun\u003e\n# pred;;\n- : int -\u003e int = \u003cfun\u003e\n# max;;\n- : int -\u003e int -\u003e int = \u003cfun\u003e\n# min;;\n- : int -\u003e int -\u003e int = \u003cfun\u003e\n# abs;;\n- : int -\u003e int = \u003cfun\u003e\n# max_int;;\n- : int = 4611686018427387903\n# min_int;;\n- : int = -4611686018427387904\n\n# not;;\n- : bool -\u003e bool = \u003cfun\u003e\n\n# print_bool;;\n- : bool -\u003e unit = \u003cfun\u003e\n# print_int;;\n- : int -\u003e unit = \u003cfun\u003e\n# print_newline;;\n- : unit -\u003e unit = \u003cfun\u003e\n\n# ignore;;\n- : 'a -\u003e unit = \u003cfun\u003e\n\n# exit;;\n- : int -\u003e unit = \u003cfun\u003e\n```\n\n## Examples\nYou can check more examples in `sample.ldti` and `test/test_examples.ml`.\n```\n(* Simple examples which use the dynamic type *)\n# (fun (x:?) -\u003e x + 2) 3;;\n- : int = 5\n\n# (fun (x:?) -\u003e x + 2) true;;\nBlame on the expression side:\nline 2, character 14 -- line 2, character 15\n\n# (fun (x:?) -\u003e x) (fun y -\u003e y);;\n- : ? = \u003cfun\u003e: ? -\u003e ? =\u003e ?\n\n(* DTI: a type of y is instantiated to int *)\n# (fun (x:?) -\u003e x 2) (fun y -\u003e y);;\n- : ? = 2: int =\u003e ?\n\n(* DTI: a type of x is instantiated to X1-\u003eX2 where X1 and X2 are fresh,\n   then X1 and X2 are instantiated to int *)\n# (fun (f:?) -\u003e f 2) ((fun x -\u003e x) ((fun (y:?) -\u003e y) (fun z -\u003e z + 1)));;\n- : ? = 3: int =\u003e ?\n\n(* DTI: a type of x is instantiated to unit, then raises blame\n   because a cast \"true: bool =\u003e ? =\u003e unit\" fails *)\n# (fun (f:?) -\u003e f (); f true) (fun x -\u003e x);;\nBlame on the environment side:\nline 6, character 29 -- line 6, character 39\n\n(* Let polymorphism *)\n# let id x = x;;\nid : 'a -\u003e 'a = \u003cfun\u003e\n\n# let dynid (x:?) = x;;\ndynid : ? -\u003e ? = \u003cfun\u003e\n\n(* succ is in the standard library *)\n# succ;;\n- : int -\u003e int = \u003cfun\u003e\n\n# (fun (f:?) -\u003e f 2) (id (dynid succ));;\n- : ? = 3: int =\u003e ?\n\n# (fun (f:?) -\u003e f true) (id (dynid succ));;\nBlame on the environment side:\nline 11, character 33 -- line 11, character 37\n\n(* A polymorphic function which does not behave parametric *)\n# let succ_non_para x = 1 + dynid x;;\nsucc_non_para : 'a -\u003e int = \u003cfun\u003e\n\n(* Returns a value when applied to an interger value *)\n# succ_non_para 3;;\n- : int = 4\n\n(* Returns a value when applied to a non-interger value *)\n# succ_non_para true;;\nBlame on the expression side:\nline 12, character 26 -- line 12, character 33\n\n(* \"let x = v in e\" and \"e[x:=v]\" should behave the same way *)\n# (fun x -\u003e 1 + dynid x) 3;;\n- : int = 4\n\n(* The following example uses ν during the evaluation *)\n# let nu_fun x = ((fun y -\u003e y): ? -\u003e ?) x;;\nnu_fun : 'a -\u003e ? = \u003cfun\u003e\n\n(* The following expression is translated into \"nu_fun[unit,ν]; nu_fun[int,ν];;\"\n   and returns a value *)\n# nu_fun (); nu_fun 3;;\n- : ? = 3: int =\u003e ?\n\n(* Recursion *)\n# let rec sum (n:?) = if n \u003c 1 then 0 else n + sum (n - 1);;\nsum : ? -\u003e int = \u003cfun\u003e\n\n# sum 100;;\n- : int = 5050\n\n# sum true;;\nBlame on the expression side:\nline 18, character 23 -- line 18, character 24\n\n# exit 0;;\n```\n\n## Contents\n- `bin`: Entry point of the interpreter\n- `lib`: Implementation of the calculus\n- `test`: Unit tests\n\n## License\nMIT License. See [LICENSE](LICENSE).\n\n## References\n- [Ronald Garcia and Matteo Cimini. Principal Type Schemes for Gradual Programs. In Proc. of ACM POPL, 2015.](https://dl.acm.org/citation.cfm?id=2676992)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fymyzk%2Flambda-dti","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fymyzk%2Flambda-dti","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fymyzk%2Flambda-dti/lists"}