{"id":28033087,"url":"https://github.com/terror/val","last_synced_at":"2025-05-11T09:12:22.024Z","repository":{"id":287614657,"uuid":"964820196","full_name":"terror/val","owner":"terror","description":"An arbitrary precision calculator language","archived":false,"fork":false,"pushed_at":"2025-05-05T18:07:20.000Z","size":605,"stargazers_count":99,"open_issues_count":6,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-11T09:12:15.518Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://terror.github.io/val/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terror.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING","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,"zenodo":null}},"created_at":"2025-04-11T20:59:09.000Z","updated_at":"2025-05-05T18:07:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"a143540a-f703-49da-9469-ae36c9c94d60","html_url":"https://github.com/terror/val","commit_stats":null,"previous_names":["terror/val"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terror%2Fval","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terror%2Fval/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terror%2Fval/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terror%2Fval/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terror","download_url":"https://codeload.github.com/terror/val/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253540838,"owners_count":21924537,"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":"2025-05-11T09:12:21.425Z","updated_at":"2025-05-11T09:12:22.017Z","avatar_url":"https://github.com/terror.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"## val\n\n[![release](https://img.shields.io/github/release/terror/val.svg?label=release\u0026style=flat\u0026labelColor=282c34\u0026logo=github)](https://github.com/terror/val/releases/latest)\n[![crates.io](https://shields.io/crates/v/val.svg)](https://crates.io/crates/val)\n[![CI](https://github.com/terror/val/actions/workflows/ci.yaml/badge.svg)](https://github.com/terror/val/actions/workflows/ci.yaml)\n[![docs.rs](https://img.shields.io/docsrs/val)](https://docs.rs/val)\n[![dependency status](https://deps.rs/repo/github/terror/val/status.svg)](https://deps.rs/repo/github/terror/val)\n\n**val** (e**val**) is a simple arbitrary precision calculator language built\non top of [**chumsky**](https://github.com/zesterer/chumsky) and\n[**ariadne**](https://github.com/zesterer/ariadne).\n\n\u003cimg width=\"1667\" alt=\"val\" src=\"https://github.com/user-attachments/assets/7f417960-adf3-43e3-a50c-4710ea1a653c\" /\u003e\n\n## Installation\n\n`val` should run on any system, including Linux, MacOS, and the BSDs.\n\nThe easiest way to install it is by using [cargo](https://doc.rust-lang.org/cargo/index.html),\nthe Rust package manager:\n\n```bash\ncargo install val\n```\n\n### Pre-built binaries\n\nPre-built binaries for Linux, MacOS, and Windows can be found on [the releases\npage](https://github.com/terror/val/releases).\n\n## Usage\n\nThe primary way to use **val** is via the provided command-line interface. There\nis currently ongoing work on a Rust library and web playground, which will\nprovide a few extra ways to interact with the runtime.\n\nBelow is the output of `val --help`, which describes some of the\narguments/options we support:\n\n```present cargo run -- --help\nval 0.3.6\nLiam \u003cliam@scalzulli.com\u003e\nAn arbitrary precision calculator language\n\nUsage: val [OPTIONS] [FILENAME]\n\nArguments:\n  [FILENAME]  File to evaluate\n\nOptions:\n  -e, --expression \u003cEXPRESSION\u003e        Expression to evaluate\n  -l, --load \u003cLOAD\u003e                    Load files before entering the REPL\n  -p, --precision \u003cPRECISION\u003e          Decimal precision to use for calculations [default: 1024]\n  -r, --rounding-mode \u003cROUNDING_MODE\u003e  Rounding mode to use for calculations [default: to-even]\n      --stack-size \u003cSTACK_SIZE\u003e        Stack size in MB for evaluations [default: 128]\n  -h, --help                           Print help\n  -V, --version                        Print version\n```\n\nRunning **val** on its own will spawn a repl (read–eval–print loop) environment,\nwhere you can evaluate arbitrary **val** code and see its output immediately. We\nuse [rustyline](https://github.com/kkawakam/rustyline) for its implementation,\nand we support a few quality of life features:\n\n- Syntax highlighting (see image above)\n- Persistent command history\n- Emacs-style editing support by default\n- Filename completions\n- Hints (virtual text pulled from history)\n\nThe **val** language supports not only expressions, but quite a few\n[statements](https://github.com/terror/val/blob/ea0c163934ee3f4afe118384b1281d296f116539/src/ast.rs#L35) as well.\nYou may want to save **val** programs and execute them later, so\nthe command-line interface provides a way to evaluate entire files.\n\nFor instance, lets say you have the following **val** program at\n`factorial.val`:\n\n```rust\nfn factorial(n) {\n  if (n \u003c= 1) {\n    return 1\n  } else {\n    return n * factorial(n - 1)\n  }\n}\n\nprintln(factorial(5));\n```\n\nYou can execute this program by running `val factorial.val`, which will write to\nstandard output `120`.\n\nLastly, you may want to evaluate a **val** expression and use it within another\nprogram. The tool supports executing arbitrary expressions inline using the\n`--expression` or `-e` option:\n\n```bash\nval -p 53 -e 'sin(2) * e ^ pi * cos(sum([1, 2, 3]))'\n20.203684508229124193\n```\n\n**n.b.** The `--expression` option and `filename` argument are mutually\nexclusive.\n\n## Features\n\nThis section describes some of the language features **val** implements in\ndetail, and should serve as a guide to anyone wanting to write a **val**\nprogram.\n\n### Statements\n\n**val** supports a few statement constructs such as `if`, `while`, `loop`, `fn`,\n`return`, etc. Check out the [grammar](https://github.com/terror/val/blob/master/GRAMMAR.txt)\nfor all of the various statement types.\n\nHere's an example showcasing most of them in action:\n\n```rust\nfn fib(n) {\n  if (n \u003c= 1) {\n    return n\n  }\n\n  return fib(n - 1) + fib(n - 2)\n}\n\ni = 0\n\nwhile (i \u003c 10) {\n  println(\"fib(\" + i + \") = \" + fib(i))\n  i = i + 1\n}\n```\n\n### Expressions\n\n**val** supports a variety of expressions that can be combined to form more\ncomplex operations:\n\n| Category       | Operation             | Syntax                        | Example                              |\n| -------------- | --------------------- | ----------------------------- | ------------------------------------ |\n| **Arithmetic** | Addition              | `a + b`                       | `1 + 2`                              |\n|                | Subtraction           | `a - b`                       | `5 - 3`                              |\n|                | Multiplication        | `a * b`                       | `4 * 2`                              |\n|                | Division              | `a / b`                       | `10 / 2`                             |\n|                | Modulo                | `a % b`                       | `7 % 3`                              |\n|                | Exponentiation        | `a ^ b`                       | `2 ^ 3`                              |\n|                | Negation              | `-a`                          | `-5`                                 |\n| **Logical**    | And                   | `a \u0026\u0026 b`                      | `true \u0026\u0026 false`                      |\n|                | Or                    | \u003ccode\u003ea \u0026#124;\u0026#124; b\u003c/code\u003e | \u003ccode\u003etrue \u0026#124;\u0026#124; false\u003c/code\u003e |\n|                | Not                   | `!a`                          | `!true`                              |\n| **Comparison** | Equal                 | `a == b`                      | `x == 10`                            |\n|                | Not Equal             | `a != b`                      | `y != 20`                            |\n|                | Less Than             | `a \u003c b`                       | `a \u003c b`                              |\n|                | Less Than or Equal    | `a \u003c= b`                      | `i \u003c= 5`                             |\n|                | Greater Than          | `a \u003e b`                       | `count \u003e 0`                          |\n|                | Greater Than or Equal | `a \u003e= b`                      | `value \u003e= 100`                       |\n| **Other**      | Function Call         | `function(args)`              | `sin(x)`                             |\n|                | List Indexing         | `list[index]`                 | `numbers[0]`                         |\n|                | List Creation         | `[item1, item2, ...]`         | `[1, 2, 3]`                          |\n|                | List Concatenation    | `list1 + list2`               | `[1, 2] + [3, 4]`                    |\n|                | String Concatenation  | `string1 + string2`           | `\"Hello, \" + name`                   |\n|                | Variable Reference    | `identifier`                  | `x`                                  |\n\n### Values\n\n**val** has several primitive value types:\n\n#### Number\n\nNumeric values are represented as arbitrary precision floating point numbers (using\n[astro_float](https://docs.rs/astro-float/latest/astro_float/index.html) under\nthe hood):\n\n```rust\n\u003e pi\n3.141592653589793115997963468544185161590576171875\n\u003e e\n2.718281828459045090795598298427648842334747314453125\n\u003e sin(2) * e ^ pi * cos(sum([1, 2, 3]))\n16.4814557939128835908118223753548409318930600432600320575175542910885566534716862696709583557263450637540094805515971245058657340687939442764118452427864231041058959960049996970569867866035825048029794926250103816423751837050040821914044725396611746570949840536443560831710407959633707222226883928822125018007\n\u003e\n```\n\nYou can specify the rounding mode, and what sort of precision you'd like to see\nin the output by using the `--rounding-mode` and `--precision` options\nrespectively.\n\n#### Boolean\n\nBoolean values represent truth values:\n\n```rust\na = true\nb = false\nc = a \u0026\u0026 b\nd = a || b\ne = !a\n```\n\n#### String\n\nText values enclosed in single or double quotes:\n\n```rust\ngreeting = \"Hello\"\nname = 'World'\nmessage = greeting + \", \" + name + \"!\"\n```\n\n#### List\n\nCollections of values of any type:\n\n```rust\nnumbers = [1, 2, 3, 4, 5]\nmixed = [1, \"two\", true, [3, 4]]\nempty = []\nfirst = numbers[0]\nnumbers[0] = 10\ncombined = numbers + [6, 7]\n```\n\n#### Function\n\nA function is a value, and can be used in assignments, passed around to other\nfunctions, etc.\n\nCheck out the [higher order functions example](https://github.com/terror/val/blob/master/examples/hoc.val)\nfor how this works.\n\n```rust\nfn reduce(l, f, initial) {\n  i = 0\n\n  result = initial\n\n  while (i \u003c len(l)) {\n    result = f(result, l[i])\n    i = i + 1\n  }\n\n  return result\n}\n\nfn sum(a, b) {\n  return a + b\n}\n\nl = [1, 2, 3, 4, 5]\n\nprintln(reduce(l, sum, 0))\n```\n\n#### Null\n\nRepresents the absence of a value.\n\n```rust\nfn search(l, x) {\n  i = 0\n\n  while (i \u003c len(l)) {\n    if (l[i] == x) {\n      return i\n    }\n\n    i = i + 1\n  }\n}\n\nl = [1, 2, 3, 4, 5]\n\nindex = search(l, 6)\n\nif (index == null) {\n  println(\"Value not found\")\n} else {\n  println(\"Value found at index \" + index)\n}\n```\n\n### Built-ins\n\n**val** offers a many built-in functions and constants:\n\n| Category          | Function/Constant   | Description                        | Example                  |\n| ----------------- | ------------------- | ---------------------------------- | ------------------------ |\n| **Constants**     | `pi`                | Mathematical constant π (≈3.14159) | `area = pi * r^2`        |\n|                   | `e`                 | Mathematical constant e (≈2.71828) | `growth = e^rate`        |\n|                   | `phi`               | Golden ratio φ (≈1.61803)          | `ratio = phi * width`    |\n|                   | `tau`               | Tau constant τ (≈6.28318, 2π)      | `circum = tau * r`       |\n| **Trigonometric** | `sin(x)`            | Sine of x (radians)                | `sin(pi/2)`              |\n|                   | `cos(x)`            | Cosine of x (radians)              | `cos(0)`                 |\n|                   | `tan(x)`            | Tangent of x (radians)             | `tan(pi/4)`              |\n|                   | `csc(x)`            | Cosecant of x (radians)            | `csc(pi/6)`              |\n|                   | `sec(x)`            | Secant of x (radians)              | `sec(0)`                 |\n|                   | `cot(x)`            | Cotangent of x (radians)           | `cot(pi/4)`              |\n| **Inverse Trig**  | `asin(x)`           | Arc sine (-1≤x≤1)                  | `asin(0.5)`              |\n|                   | `acos(x)`           | Arc cosine (-1≤x≤1)                | `acos(0.5)`              |\n|                   | `arc(x)`            | Arc tangent                        | `arc(1)`                 |\n|                   | `acsc(x)`           | Arc cosecant (abs(x)≥1)            | `acsc(2)`                |\n|                   | `asec(x)`           | Arc secant (abs(x)≥1)              | `asec(2)`                |\n|                   | `acot(x)`           | Arc cotangent                      | `acot(1)`                |\n| **Hyperbolic**    | `sinh(x)`           | Hyperbolic sine                    | `sinh(1)`                |\n|                   | `cosh(x)`           | Hyperbolic cosine                  | `cosh(1)`                |\n|                   | `tanh(x)`           | Hyperbolic tangent                 | `tanh(1)`                |\n| **Logarithmic**   | `ln(x)`             | Natural logarithm                  | `ln(e)`                  |\n|                   | `log2(x)`           | Base-2 logarithm                   | `log2(8)`                |\n|                   | `log10(x)`          | Base-10 logarithm                  | `log10(100)`             |\n|                   | `e(x)`              | e raised to power x                | `e(2)`                   |\n| **Numeric**       | `sqrt(x)`           | Square root (x≥0)                  | `sqrt(16)`               |\n|                   | `ceil(x)`           | Round up to integer                | `ceil(4.3)`              |\n|                   | `floor(x)`          | Round down to integer              | `floor(4.7)`             |\n|                   | `abs(x)`            | Absolute value                     | `abs(-5)`                |\n|                   | `gcd(a, b)`         | Greatest common divisor            | `gcd(12, 8)`             |\n|                   | `lcm(a, b)`         | Least common multiple              | `lcm(4, 6)`              |\n| **Collections**   | `len(x)`            | Length of list or string           | `len(\"hello\")`           |\n|                   | `sum(list)`         | Sum list elements                  | `sum([1,2,3])`           |\n|                   | `append(list, val)` | Add element to end of list         | `append([1,2], 3)`       |\n| **Conversion**    | `int(x)`            | Convert to integer                 | `int(\"42\")`              |\n|                   | `float(x)`          | Convert to float                   | `float(\"3.14\")`          |\n|                   | `bool(x)`           | Convert to boolean                 | `bool(1)`                |\n|                   | `list(x)`           | Convert to list                    | `list(\"abc\")`            |\n| **I/O**           | `print(...)`        | Print without newline              | `print(\"Hello\")`         |\n|                   | `println(...)`      | Print with newline                 | `println(\"World\")`       |\n|                   | `input([prompt])`   | Read line from stdin               | `name = input(\"Name: \")` |\n| **String**        | `split(str, delim)` | Split string                       | `split(\"a,b,c\", \",\")`    |\n|                   | `join(list, delim)` | Join list elements                 | `join([\"a\",\"b\"], \"-\")`   |\n| **Program**       | `exit([code])`      | Exit program                       | `exit(1)`                |\n|                   | `quit([code])`      | Alias for exit                     | `quit(0)`                |\n\n## Prior Art\n\n[bc(1)](https://linux.die.net/man/1/bc) - An arbitrary precision calculator\nlanguage\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterror%2Fval","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterror%2Fval","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterror%2Fval/lists"}