{"id":13393843,"url":"https://github.com/rhysd/gocaml","last_synced_at":"2025-04-04T21:07:57.921Z","repository":{"id":66059540,"uuid":"80016833","full_name":"rhysd/gocaml","owner":"rhysd","description":":camel: Statically typed functional programming language implementation with Go and LLVM","archived":false,"fork":false,"pushed_at":"2020-07-04T04:46:48.000Z","size":736,"stargazers_count":754,"open_issues_count":1,"forks_count":29,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-03-28T20:07:22.674Z","etag":null,"topics":["compiler","go","golang","language","llvm","ml","programming-language"],"latest_commit_sha":null,"homepage":"","language":"Go","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/rhysd.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}},"created_at":"2017-01-25T13:27:50.000Z","updated_at":"2025-03-03T10:49:08.000Z","dependencies_parsed_at":"2023-09-05T00:45:16.696Z","dependency_job_id":null,"html_url":"https://github.com/rhysd/gocaml","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhysd%2Fgocaml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhysd%2Fgocaml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhysd%2Fgocaml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhysd%2Fgocaml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhysd","download_url":"https://codeload.github.com/rhysd/gocaml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247249525,"owners_count":20908212,"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":["compiler","go","golang","language","llvm","ml","programming-language"],"created_at":"2024-07-30T17:01:01.223Z","updated_at":"2025-04-04T21:07:57.902Z","avatar_url":"https://github.com/rhysd.png","language":"Go","readme":"GoCaml :camel:\n==============\n[![Linux and macOS Build Status][]][Travis CI]\n[![Windows Build Status][]][Appveyor]\n[![Coverage Status][]][Codecov]\n\nGoCaml is subset of OCaml in Go based on [MinCaml][] using [LLVM][]. GoCaml adds many features to original MinCaml.\nMinCaml is a minimal subset of OCaml for educational purpose. It is statically-typed and compiled into a binary.\n\nThis project aims incremental compiler development for my own programming language.\nType inference, closure transform, mid-level IR are implemented.\n\n- [Japanese presentation (Go Conference Tokyo 2017 Spring)](https://speakerdeck.com/rhysd/go-detukurufan-yong-yan-yu-chu-li-xi-shi-zhuang-zhan-lue)\n- [Japanese presentation (builderscon 2017)](https://speakerdeck.com/rhysd/xiao-sakushi-meteyu-terukonpaira)\n\nExample:\n\n```ml\nlet rec gcd m n =\n  if m = 0 then n else\n  if m \u003c= n then gcd m (n - m) else\n  gcd n (m - n) in\nprint_int (gcd 21600 337500)\n```\n\nYou can see [more examples][examples]. (e.g. [Brainfxxk interpreter][Brainfxxk interpreter example], [N-Queens puzzle][N-Queens puzzle example])\n\n## Tasks\n\n- [x] Lexer -\u003e ([doc][syntax doc])\n- [x] Parser with [goyacc][] -\u003e ([doc][syntax doc])\n- [x] Alpha transform ([doc][sema doc])\n- [x] Type inference (Hindley Milner monomorphic type system) -\u003e ([doc][sema doc])\n- [x] mid-level intermediate representation (MIR) ([doc][mir doc])\n- [x] K normalization from AST into MIR ([doc][mir doc])\n- [x] Closure transform ([doc][closure doc])\n- [x] Code generation (LLVM IR, assembly, object, executable) using [LLVM][] ([doc][codegen doc])\n- [x] LLVM IR level optimization passes\n- [x] Garbage collection with [Boehm GC][]\n- [x] Debug information (DWARF) using LLVM's Debug Info builder\n\n## Difference from Original MinCaml\n\n- MinCaml assumes external symbols' types are `int` when it can't be inferred. GoCaml requires explicit declaration for external\n  symbols with `external` syntax like OCaml. All external symbols (except for builtins) must be declared. Otherwise, undeclared\n  symbols are reported undefined symbols as compilation error.\n- MinCaml allows `-` unary operator for float literal. So for example `-3.14` is valid but `-f` (where `f` is `float`) is not valid.\n  GoCaml does not allow `-` unary operator for float values totally. You need to use `-.` unary operator instead (e.g. `-.3.14`).\n- GoCaml adds more operators. `*` and `/` for integers, `\u0026\u0026` and `||` for booleans.\n- GoCaml has string type. String value is immutable and used with slices.\n- GoCaml does not have `Array.create`, which is an alias to `Array.make`. `Array.length` is available to obtain the size of array\n  and `[| ... |]` literal is available to create an array with specific elements.\n- Some useful built-in functions are added (described in below section).\n- [Option type][] is implemented in GoCaml. Please see below 'Option Type' section or [test cases][option type test cases].\n- GoCaml has `fun` syntax to make an anonymous funcion or closure like `fun x y -\u003e x + y`.\n- GoCaml has type annotations syntax. Users can specify types explicitly.\n- Symbols named `_` are ignored.\n- Type alias using `type` keyword.\n\n## Language Spec\n\n### Program\n\nProgram is represented as one expression which MUST be evaluated as unit type. So `()` is the\nsmallest program for GoCaml.\n\n### Sequence Expression\n\nSequenced program can be represented by joining multiple expressons with `;`.\n\n```ml\ne1; e2; e3; e4\n```\n\nIn above program, expressions are evaluated in order of `e1 -\u003e e2 -\u003e e3 -\u003e e4` and the sequenced\nexpression is evaluated to the value of `e4`.\nProgram must be evaluated to unit type, so the `e4` expression must be evaluated to `()` (unit value).\n\n### Comments\n\nThere is a block comment syntax. It starts with `(*` and ends with `*)`. Any comment must be closed\nwith `*)`, otherwise it falls into syntax error.\n\n```ml\n(*\n   This is comment.\n*)\n```\n\n### Constants\n\nThere are unit, integer, boolean, float and string constants.\n\n```ml\n(* integer *)\n42;\n\n(* float *)\n3.0;\n3.14e+10;\n3.14e-10;\n1.;\n\n(* boolean *)\ntrue;\nfalse;\n\n(* string *)\n\"hello, world\";\n\"contains\\tescapes\\n\";\n\n(* only one constant which is typed to unit *)\n()\n```\n\n### Show values\n\n`print_*` and `println_*` built-in functions are available to output values to stdout.\n\n```ml\nprint_int 42;\nprintln_bool true\n```\n\nPlease see 'Built-in functions' section below for more detail.\n\n### Unary operators\n\nYou can use some unary prefixed operators.\n\n```ml\n-42;\n\n(* GoCaml distinguishes float and int in operators. -. is a float version of - *)\n-.3.14;\n\nnot true;\n\n()\n```\n\n### Arithmetic binary operators\n\nAs mentioned above, GoCaml distinguishes int and float in operators. Operators for float values are\nsuffixed by `.` (dot).\n\n```ml\n(* integer calculation *)\n1 + 2;\n1 - 2;\n1 * 2;\n1 / 2;\n\n(* float calculation *)\n1.0 +. 2.0;\n1.0 -. 2.0;\n1.0 *. 2.0;\n1.0 /. 2.0;\n\n()\n```\n\nInteger operators must have integer values as their operands. And float operators must have float\nvalues as their operands. There is no implicit conversion. You need to convert explicitly by using\nbuilt-in functions (e.g. `3.14 +. (int_to_float 42)`).\n\nNote that strings don't have any operators for concatenating two strings or slicing sub string.\nThey can be done with `str_concat` and `str_sub` built-in functions (See 'Built-in Functions' section).\n\n### Relational operators\n\nEqual operator is `=` (NOT `==`), Not-equal operator is `\u003c\u003e`. Compare operators are the same as C\n(`\u003c`, `\u003c=`, `\u003e` and `\u003e=`).\n\n```ml\n42 = 42; (* =\u003e true *)\n42 \u003c\u003e 42; (* =\u003e false *)\n\n3.14 \u003e 2.0;\n1.0 \u003c 3.0;\n2.0 \u003e= 2.0;\n1.0 \u003c= 3.0;\n\n()\n```\n\nTuples (described below) and strings can be compared with `=` or `\u003c\u003e`, but cannot be compared with\n`\u003c`, `\u003c=`, `\u003e` and `\u003e=`. Arrays (described below) cannot be compared directly with any compare\noperators. You need to compare each element explicitly.\n\n### Logical operators\n\n`\u0026\u0026` and `||` are available for boolean values.\n\n```ml\nprintln_bool (true || false \u0026\u0026 false || false)\n```\n\n### Variable\n\n`let` expression binds some value to a variable.\n\n```ml\n(* 42 is bound to a *)\nlet a = 42 in\n(* You can use the variable as value in any expression *)\na + 4;\n\n()\n```\n\nThe syntax is `let {name} = {e1} in {e2}`. `e2` will be evaluated where `e1` is bound to `name`.\nBy chain `let`, you can define multiple variables.\n\n```ml\nlet pi = 3.141592 in\nlet r = 2 in\nlet area = r *. r *. pi in\nprint_float area\n```\n\nAnd you can redefine the same name variable as already-defined ones.\n\n```ml\nlet a = 42 in\nprintln_int a;\nlet a = true in\nprintln_bool a\n```\n\nThe first `a` and the second `a` are different variable. Second one just shadows first one.\nSo you can always redefine any variable names as any type. Shadowed variable can be no longer referred.\n\nFunctions are first-class object in GoCaml. So you can also bind functions to variable as value.\n\n```ml\nlet rec hello _ = println_str \"hello\" in\nlet f = hello in\n\n(* Shows \"hello\" *)\nf ();\n\n(* Binds external function *)\nlet p = println_str in\n\n(* Shows \"hi\" *)\np \"hi\"\n```\n\n### Functions\n\n`let rec` is a keyword to define a function. Syntax is `let rec name params... = e1 in e2` where\nfunction `name` is defined as `e1` and then `e2` will be evaluated.\n`f a b c` is an expression to apply function `f` with argument `a`, `b` and `c`.\nAs long as the argument is simple, you don't need to use `()`.\n\nNote that, if you use some complicated expression (for example, binary operators), you need to use\n`()` like `f (a+b) c`. If you specify `f a + b c`, it would be parsed as `(f a) + (b c)`.\n\n```ml\nlet rec f a b c = a + b + c in\nlet d = f 10 20 30 in\n\n(* Output: 60 *)\nprintln_int d\n```\n\nYou can make a recursive function as below.\n\n```ml\nlet rec fib x =\n    if x \u003c= 1 then 1 else\n    fib (x - 1) + fib (x - 2)\nin\nprintln_int (fib 10)\n```\n\nFunctions can be nested.\n\n```ml\nlet rec sqrt x =\n    let rec abs x = if x \u003e 0.0 then x else -.x in\n    let rec go z p =\n        if abs (p -. z) \u003c= 0.00001 then z else\n        let (p, z) = z, z -. (z *. z -. x) /. (2.0 *. z) in\n        go z p\n    in\n    go x 0.0\nin\nprintln_float (sqrt 10.0)\n\n(* Error because of out of scope: go 10.0 0.0 *)\n```\n\nIn above example, `abs` and `go` is nested in `sqrt`. Nested function is a hidden implementation of\nthe outer function because inner scope is not visible from outside.\n\nFunctions can capture any outer variables (=environment). Functions which captured outer\nenvironment are called 'closure'.  As many functional languages or modern languages,\nGoCaml has closure functions.\n\n```ml\n(* Define variable *)\nlet pi = 3.14 in\n\n(* Captures outer defined variable 'pi' into its body *)\nlet rec circle r = r *. r *. pi in\n\n(* Invoke closure *)\nprintln_float (circle 10.0)\n```\n\nBelow is a bit more complicated example:\n\n```ml\nlet rec make_adder x =\n    let z = 1 in\n    let rec f y = x + y + z in\n    f\nin\nlet add = make_adder 3 in\n\n(* Output: 104 *)\nprintln_int (add 100)\n```\n\nHere, inner function `f` captures hidden variable `special_value`. `make_special_value_adder`\nreturns a closure which captured the variable.\n\n### Lambda\n\nFunctions can be made without names using `fun` syntax.\n\n```ml\n(* Make a lambda and bind it to foo *)\nlet add = fun x y -\u003e x + y in\n\n(* Above is like below, but the function is anonymous *)\nlet rec add2 x y in x + y in\n\nprintln_int (add 1 10);\nprintln_int (add2 1 10);\n```\n\nIt's useful when passing a function without considering its name.\n\n```ml\nlet rec quick_sort xs pred =\n    (* ...snip *)\nin\nlet a = Array.make 10 0 in\nlet sorted = quick_sort a (fun l r -\u003e l \u003c r) in\n()\n```\n\nLambda does not have its name, so it cannot be called recursively.\n\nUsing lambda, above `make_adder` can be implemented as following:\n\n```ml\nlet rec make_adder x =\n    let z = 1 in\n    fun x y -\u003e x + y + z\nin\n...\n```\n\n### Type Annotation\n\nType can be specified explicitly at any expression, parameter and return type of function with `:`\n\nTypes can be written in the same syntax as other ML languages.\n\n- Primitive: `int`, `float`, `bool`, `string`\n- Any type: `_`\n- Tuple: `t1 * t2 * ... * tn` (e.g. `int * bool`)\n- Function: `a -\u003e b -\u003e ... -\u003e r` (e.g. if `f` takes `int` and `bool` and returns `string`, then `f: int -\u003e bool -\u003e string`)\n- Array: `t array` (e.g. `int array`, `int array array`)\n- Option: `t option` (e.g. `int option` `(int -\u003e bool) option`)\n\nTypes can be specified in code as following. Compiler will look and check them in type inference.\n\n```ml\n(* Type of variable *)\nlet v: int = 42 in\n\n(* Type of parameters *)\nlet rec f (x:int) = x + 10 in\nlet f = fun (x:int) -\u003e x + 10 in\n\n(* Type of return value *)\nlet rec f x: string = int_to_str x in\nlet f = fun x: string -\u003e int_to_str x in\n\n(* Type of parameter and return value *)\nlet rec f (x:int): string = int_to_str x in\nlet f = fun (x:int): string -\u003e int_to_str x in\n\n(* Type of tuple at `let` *)\nlet (a, b): int * bool = 42, bool in\n\n(* Array type *)\nlet a: bool array = Array.make 3 true in\nlet a: int array array = Array.make 3 (Array.make 3 42) in\n\n(* Option type *)\nlet o: int option = None in\nlet o: (int array * (int -\u003e bool)) option = None in\n\n(* '_' means 'any'. Specify type partially *)\nlet (a, b): _ * _ = 42, bool in\nlet f: _ -\u003e _ = fun x -\u003e x in\nlet a: _ array = Array.make 3 true in\n\n()\n```\n\n### Type Alias\n\n`type {name} = {type};` syntax declares type alias. It can be declared on toplevel. It means that\nall type aliases must be put before any expression.\n\n```ml\ntype board = int array array;\ntype point = int * int;\nlet p: point = 1, 2 in\nlet b: board = Array.make 4 (Array.make 4 0) in\n()\n```\n\nIn above example, `board` is an alias of `int array array`. It can be used the same as `int array array`.\nNote that `type` does not make another type here. Just make an alias.\n\n### Tuples\n\nN-elements tuple can be created with comma-separated expression `e1, e2, ..., en`. Element of tuple\ncan be extracted with `let` expression.\n\n```ml\n(* (int, bool, string) is bound to t *)\nlet t = 1, true, \"aaa\" in\n\n(* Destructuring tuple with `let` expression *)\nlet i, b, s = t in\n\nlet rec fst pair = let x, _ = pair in x in\n\n(* Show '42' *)\nprintln_int (fst (42, true))\n```\n\n### Arrays\n\nArray can be created with `Array.make size elem` where created array is allocated with `size` elements\nand all elements are initialized as `elem`. And array literal `[| e1; e2; ... |]` is also supported which\nallocates an array with specified (`e1`, `e2`...) elements.\n\n`arr.(idx)` accesses to the element of array where `arr` is an array and `idx` is an integer.\nAnd `arr.(idx) \u003c- val` updates the `idx`th element to `val`.\n\n```ml\n(* Make boolean array whose size is 42 *)\nlet arr = Array.make 42 true in\n\n(* Output: true *)\nprintln_bool arr.(8);\n\n(* Update element *)\narr.(8) \u003c- false;\n\n(* Output: false *)\nprintln_bool arr.(8);\n\n(* Make an array with 1, 2 and 3 elements *)\nlet lit = [| 1; 2; 3 |] in\n\n(* Output: 2 *)\nprintln_int lit.(1);\n\n(* Output: 3 *)\nprintln_int (Array.length lit)\n```\n\nNote that arrays are NOT immutable because of performance (GoCaml doesn't have persistentarray).\n`e1.(e2) \u003c- e3` is always evaluated to `()` and updates the element destructively.\nAccessing to out of bounds of arrays causes undefined behavior.\n\nAnd note that list literal (`[e1; e2; ...]`) is not supported yet. Please do not be confused.\n\n### Option Type\n\nOption type represents some value or none.\n\n```ml\nlet rec print o =\n    match o with\n      | Some i -\u003e println_int o\n      | None   -\u003e println_str \"none\"\nin\nprint None;\nprint (Some 42)\n```\n\nFirst `|` can be omitted so you can write it in one line.\n\n```ml\nif match o with Some i -\u003e true | None -\u003e false then\n  println_str \"some!\"\nelse\n  println_str \"none...\"\n```\n\nOption values can be compared with `=` or `\u003c\u003e` directly.\n\n```ml\nlet rec is_some x = x \u003c\u003e None in\nlet rec is_none x = (x = None) in\n\nprintln_bool (is_some (Some 42));\nprintln_bool (is_some None);\nprintln_bool (is_none (Some 42));\nprintln_bool (is_none None)\n```\n\nCurrently `match with` expression is only for option type because GoCaml doesn't have variant types.\n\n### Ignored Symbol `_`\n\nVariables named `_` are ignored. It's useful if the variable is never used.\n\n```ml\n(* Ignored variable *)\nlet _ = 42 in\n\n(* Ignored parameter *)\nlet rec first x _ _ = x in\n\n(* Ignored element of tuple *)\nlet (_, second, _) = 1, \"foo\", true in\n\n(* Error! Cannot refer ignored variable *)\nprint_int _\n```\n\nIf a type of an ignored variable is never determined, compiler regards its type as `()` and\ncompilation will pass.\n\n```\nlet f _ = 42 in\nprintln_int 42\n```\n\nIn above program, the type of ignored variable `_` will never be determined because function `f` is\nnever used. In this case, compiler regards type of `f` as `unit -\u003e int` and compilation will continue.\n\n### External Symbols\n\nAll external symbol must be declared with `external` syntax.\n\n```ml\nexternal name: type = \"c_name\";\n```\n\nThe `name` is a symbol name of the external symbol. And the `\"c_name\"` is a symbol name linked in\nC level. The `type` cannot contain any generic type variable and `_`.\nFor example, when you define `gocaml_int foo(gocaml_int i)` function in C, then you need to declare\n`\"foo\"` external C name with type `int -\u003e int` to use it from GoCaml.\n\n```ml\nexternal foo: int -\u003e int = \"foo\";\nfoo 42\n```\n\nOr when you define a global variable `gocaml_int x` in C, you need to declare external `\"x\"` C name\nto use the global variable value from GoCaml.\n\n```ml\nexternal x: int = \"x\";\nprintln_int x\n```\n\nIf C name does not exist in link phase, compiler will cause a linker error at compiling the source.\n\nLike `type` syntax, all `external` declarations should be written before any expression.\n\n## Prerequisites\n\n- Go 1.7+\n- GNU make\n- Clang or GCC (for building small runtime)\n- cmake (for building LLVM)\n- Git\n\n## Installation\n\n### Linux or macOS\n\nFor Linux or macOS, below commands build `gocaml` binary at root of the repository.\n[libgc][] is needed as dependency.\n\n```console\n# On Debian-family Linux\n$ sudo apt-get install libgc-dev\n\n# On macOS\n$ brew install go cmake bdw-gc coreutils\n\n$ mkdir -p $GOPATH/src/github.com/rhysd \u0026\u0026 cd $GOPATH/src/github.com/rhysd\n$ git clone https://github.com/rhysd/gocaml.git\n$ cd gocaml\n\n# Full-installation with building LLVM locally\n$ make\n```\n\nThe `make` command will do all. First, it clones LLVM into `$GOPATH/src/llvm.org/llvm/` and builds\nit for LLVM Go binding. Second, it builds `gocaml` binary and `gocamlrt.a` runtime. Finally, it\nruns all tests for validation.\nNote that `go get -d` is not available because `llvm.org/*` dependency is not go-gettable for now.\n\nAbove is the easiest way to install gocaml, but if you want to use system-installed LLVM instead of\nbuilding `$GOPATH/src/llvm.org/llvm`, please follow build instruction.\n\n`USE_SYSTEM_LLVM=true` will build `gocaml` binary with system-installed LLVM libraries.\nNote that it still clones LLVM repository because `$GOPATH/src/llvm.org/llvm/bindings/go/*` is\nnecessary for building gocaml.\n\nTo use `USE_SYSTEM_LLVM`, you need to install LLVM 4.0.0 or later (5.0.0 is recommended) with system's\npackage manager in advance.\n\nIf you use Debian-family Linux, use [LLVM apt repository][] or download [LLVM official binary][].\n\n```console\n$ sudo apt-get install libllvm5.0 llvm-5.0-dev\n$ export LLVM_CONFIG=llvm-config-5.0\n```\n\nIf you use macOS, use [Homebrew][]. GoCaml's installation script will automatically detect LLVM\ninstalled with Homebrew.\n\n```console\n$ brew install llvm\n```\n\nNow you can build gocaml with `USE_SYSTEM_LLVM` flag.\n\n```console\n$ USE_SYSTEM_LLVM=true make\n```\n\n### Windows\n\nCurrently Windows is not well-supported. You need to clone LLVM repository to `$GOPATH/src/llvm.org/`\nand build Go bindings of llvm-c following [the instruction][Go binding building instruction].\nIt needs `cmake` command and C++ toolchain.\n\nIt also needs to build [libgc][] static library and put it to library path.\n\nAfter installing [goyacc][], generate a parser code with it.\n\n```\n$ goyacc -o parser/grammar.go parser/grammar.go.y\n```\n\nFinally you can build `gocaml` binary with `go build`.\n\n## Usage\n\n`gocaml` command is available to compile sources. Please refer `gocaml -help`.\n\n```\nUsage: gocaml [flags] [file]\n\n  Compiler for GoCaml.\n  When file is given as argument, compiler will compile it. Otherwise, compiler\n  attempt to read from STDIN as source code to compile.\n\nFlags:\n  -analyze\n    \tAnalyze code and report errors if exist\n  -asm\n    \tEmit assembler code to stdout\n  -ast\n    \tShow AST for input\n  -dump-env\n    \tDump analyzed symbols and types information to stdout\n  -g\tCompile with debug information\n  -help\n    \tShow this help\n  -ldflags string\n    \tFlags passed to underlying linker\n  -llvm\n    \tEmit LLVM IR to stdout\n  -mir\n    \tEmit GoCaml Intermediate Language representation to stdout\n  -obj\n    \tCompile to object file\n  -opt int\n    \tOptimization level (0~3). 0: none, 1: less, 2: default, 3: aggressive (default -1)\n  -show-targets\n    \tShow all available targets\n  -target string\n    \tTarget architecture triple\n  -tokens\n    \tShow tokens for input\n```\n\nCompiled code will be linked to [small runtime][]. In runtime, some functions are defined to print\nvalues and it includes `\u003cstdlib.h\u003e` and `\u003cstdio.h\u003e`. So you can use them from GoCaml codes.\n\n`gocaml` uses `clang` for linking objects by default. If you want to use other linker, set\n`$GOCAML_LINKER_CMD` environment variable to your favorite linker command.\n\n## Program Arguments\n\nYou can access to program arguments via special global variable `argv`. `argv` is always defined\nbefore program starts.\n\n```ml\nprint_str \"argc: \"; println_int (Array.length argv);\nprint_str \"prog: \"; println_str (argv.(0))\n```\n\n## Built-in Functions\n\nBuilt-in functions are defined as external symbols.\n\n- `print_int : int -\u003e ()`\n- `print_bool : bool -\u003e ()`\n- `print_float : float -\u003e ()`\n- `print_str : string -\u003e ()`\n\nOutput the value to stdout.\n\n- `println_int : int -\u003e ()`\n- `println_bool : bool -\u003e ()`\n- `println_float : float -\u003e ()`\n- `println_str : string -\u003e ()`\n\nOutput the value to stdout with newline.\n\n- `float_to_int : float -\u003e int`\n- `int_to_float : int -\u003e float`\n- `int_to_str : int -\u003e string`\n- `str_to_int : string -\u003e int`\n- `float_to_str : float -\u003e string`\n- `str_to_float : string -\u003e float`\n\nConvert between float and int, string and int, float and int.\n\n- `str_length : string -\u003e int`\n\nReturn the size of string.\n\n- `str_concat : string -\u003e string -\u003e string`\n\nConcat two strings as a new allocated string because strings are immutable in GoCaml.\n\n- `str_sub : string -\u003e int -\u003e int -\u003e string`\n\nReturns substring of first argument. Second argument is an index to start and Third argument is an\nindex to end.\nReturns string slice `[start, end)` so it does not cause any allocation.\n\n- `get_line : () -\u003e string`\n- `get_char : () -\u003e string`\n\nGet user input by line or character and return it as string.\n\n- `to_char_code : string -\u003e int`\n- `from_char_code : int -\u003e string`\n\nCovert between a character and integer. First character of string is converted into integer and\ninteger is converted into one character string.\n\n\n- `do_garbage_collection : () -\u003e ()`\n- `enable_garbage_collection : () -\u003e ()`\n- `disable_garbage_collection : () -\u003e ()`\n\nThese functions control behavior of GC. `do_garbage_collection` runs GC with stopping the world.\n`enable_garbage_collection`/`disable_garbage_collection` starts/stops GC. (GC is enabled by default)\n\n- `bit_and : int -\u003e int -\u003e int`\n- `bit_or : int -\u003e int -\u003e int`\n- `bit_xor : int -\u003e int -\u003e int`\n- `bit_rsft : int -\u003e int -\u003e int`\n- `bit_lsft : int -\u003e int -\u003e int`\n- `bit_inv : int -\u003e int`\n\nBuilt-in functions instead of bitwise operators.\n\n- `time_now : () -\u003e int`\n\nReturns epoch time in seconds.\n\n- `read_file : string -\u003e string option`\n\nFirst argument is a file name. It returns the content of the file. If failed, it returns `None`.\n\n- `write_file : string -\u003e string -\u003e bool`\n\nIt takes file name as first argument and its content as second argument.\nIt returns wether it could write the content to the file.\n\n\n- `ceil : float -\u003e float`\n- `floor : float -\u003e float`\n- `exp : float -\u003e float`\n- `log : float -\u003e float`\n- `log10 : float -\u003e float`\n- `log1p : float -\u003e float`\n- `sqrt : float -\u003e float`\n- `sin : float -\u003e float`\n- `cos : float -\u003e float`\n- `tan : float -\u003e float`\n- `asin : float -\u003e float`\n- `acos : float -\u003e float`\n- `atan : float -\u003e float`\n- `atan2 : float -\u003e float`\n- `sinh : float -\u003e float`\n- `cosh : float -\u003e float`\n- `tanh : float -\u003e float`\n- `asinh : float -\u003e float`\n- `acosh : float -\u003e float`\n- `atanh : float -\u003e float`\n- `hypot : float -\u003e float -\u003e float`\n- `mod_float : float -\u003e float -\u003e float`\n- `modf : float -\u003e float * float`\n- `frexp : float -\u003e float * int`\n- `ldexp : float -\u003e int -\u003e float`\n\nBasic math functions. This is the same functions as defined in [OCaml's `Pervasives` module][OCaml Pervasives module].\n\n## Built-in Constants\n\n- `infinity : float`\n- `nan : float`\n\nFloating point values represent initinity and NaN. It's the same values as defined in\n[OCaml's `Pervasives` module][OCaml Pervasives module].\n\n## How to Work with C\n\nAll symbols not defined in source are treated as external symbols. So you can define it in C source\nand link it to compiled GoCaml code after.\n\nLet's say to write C code.\n\n```c\n// gocaml.h is put in runtime/ directory. Please add it to include directory path.\n#include \"gocaml.h\"\n\ngocaml_int plus100(gocaml_int const i)\n{\n    return i + 100;\n}\n```\n\nThen compile it to an object file:\n\n```\n$ clang -Wall -c plus100.c -o plus100.o\n```\n\nThen you can refer the function from GoCaml code:\n\n```ml\nprintln_int (plus100 10)\n```\n\n`println_int` is a function defined in runtime. So you don't need to care about it.\n\nFinally comile the GoCaml code and the object file together with `gocaml` compiler. You need to link\n`.o` file after compiling GoCaml code by passing the object file to `-ldflags`.\n\n```\n$ gocaml -ldflags plus100.o test.ml\n```\n\nAfter the command, you can find `test` executable. Executing by `./test` will show `110`.\n\n## Cross Compilation\n\nFor example, let's say to want to make an `x86` binary on `x86_64` Ubuntu.\n\n```\n$ cd /path/to/gocaml\n$ make clean\n# Install gcc-multilib\n$ sudo apt-get install gcc-4.8-multilib\n```\n\nThen you need to know [target triple][] string for the architecture compiler will compile into.\nThe format is `{name}-{vendor}-{sys}-{abi}`. (ABI might be omitted)\n\nYou can know all the supported targets by below command:\n\n```\n$ ./gocaml -show-targets\n```\n\nThen you can compile source into object file for the target.\n\n```\n# Create object file for specified target\n$ ./gocaml -obj -target i686-linux-gnu source.ml\n\n# Compile runtime for the target\nCC=gcc CFLAGS=-m32 make ./runtime/gocamlrt.a\n```\n\nFinally link object files into one executable binary by hand.\n\n```\n$ gcc -m32 -lgc source.o ./runtime/gocamlrt.a\n```\n\n[MinCaml]: https://github.com/esumii/min-caml\n[goyacc]: https://github.com/cznic/goyacc\n[LLVM]: http://llvm.org/\n[Linux and macOS Build Status]: https://travis-ci.org/rhysd/gocaml.svg?branch=master\n[Travis CI]: https://travis-ci.org/rhysd/gocaml/branches\n[syntax doc]: https://godoc.org/github.com/rhysd/gocaml/syntax\n[sema doc]: https://godoc.org/github.com/rhysd/gocaml/sema\n[mir doc]: https://godoc.org/github.com/rhysd/gocaml/mir\n[closure doc]: https://godoc.org/github.com/rhysd/gocaml/closure\n[codegen doc]: https://godoc.org/github.com/rhysd/gocaml/codegen\n[Boehm GC]: https://github.com/ivmai/bdwgc\n[Coverage Status]: https://codecov.io/gh/rhysd/gocaml/branch/master/graph/badge.svg\n[Codecov]: https://codecov.io/gh/rhysd/gocaml\n[Windows Build Status]: https://ci.appveyor.com/api/projects/status/7lfewhhjg57nek2v/branch/master?svg=true\n[Appveyor]: https://ci.appveyor.com/project/rhysd/gocaml/branch/master\n[small runtime]: ./runtime/gocamlrt.c\n[LLVM apt repository]: http://apt.llvm.org/\n[Homebrew]: https://brew.sh/index.html\n[libgc]: https://www.hboehm.info/gc/\n[target triple]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple\n[examples]: ./examples\n[Brainfxxk interpreter example]: ./examples/brainfxxk.ml\n[N-Queens puzzle example]: ./examples/n-queens.ml\n[LLVM official binary]: http://releases.llvm.org/download.html#5.0.0\n[Go binding building instruction]: https://github.com/llvm-mirror/llvm/blob/master/bindings/go/README.txt\n[goyacc]: https://godoc.org/golang.org/x/tools/cmd/goyacc\n[Option type]: https://en.wikipedia.org/wiki/Option_type\n[option type test cases]: ./codegen/testdata/option_values.ml\n[OCaml Pervasives module]: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html\n","funding_links":[],"categories":["Go","Compilers and Interpreters","Repositories"],"sub_categories":["Educational and Toy Projects"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhysd%2Fgocaml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhysd%2Fgocaml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhysd%2Fgocaml/lists"}