eevo script

eevo is a simple yet expressive high-level scripting language for functional programming, an experiment in how simple a practical programming language can be.

A general-purpose language in the Lisp family that is ideal for scripting, acting as an interactive shell, data/configuration files, or a scientific calculator. eevo’s portable, simple design makes it easy to embed and extend, enabling integration into existing projects and straightforward use of established libraries. Forget the boilerplate and needless ceremony: focus on the what, and let eevo handle the how.

Everything should be as simple as possible, but not simpler

Albert Einstein
def fib(n)
  "Fibonacci number of n"
  if (< n 2)
    n
    + fib((- n 1)) fib((- n 2))

fib 25  ; = 46368

A lightweight modular core allows you to choose how much of the language you need, or swap out individual components. This comes in a few layers:

While eevo is a general purpose programming language, that does not mean it is the best tool for every problem. Like all languages, eevo has many design decisions which have trade-offs in different situations. To solve problems that are ill-suited to eevo’s design (such as requiring circular references or precise mutations), authors can call upon other languages through C‑bindings (and soon WASM).

This interoperability makes it easy to offload computationally heavy code to another language or gradually replace existing code with concise scripts. This enables a dual approach to bridge languages in two directions:

Do both at the same time with different languages, allowing eevo to glue different libraries, ecosystems, and tools together.

Warning

eevo is still in active development and not yet stable. Until the v1.0 release expect breaking non-backwards compatible changes.

Features

See the language manual for complete set of features.

High-level

  • Developer can focus on important logic, not boiler-plate.
  • Let eevo worry about implementation details, optimizations, data representation.
  • Avoid premature optimization.

Functional programming

Interactive

  • Read, Evaluate, Print, Loop (REPL).

First Class Types

  • Numbers: integers Int, decimals Dec, ratios Ratio.
  • Text: strings Str, symbols (identifiers/variables) Sym.
  • Booleans: True, Nil.
  • Lists, pairs Pair,
  • Records: Rec (hash tables/maps),
    • Unordered set of key value pairs.
    • Look up tables, accept key and return corresponding value.
    • Environments (namespaces/modules/capabilities).
  • Functions with closures Func,
  • Macros functions which transform code.
  • Dependent Types
  • Void
  • Errors

Functions as the universal type

  • Records, arrays, dictionaries, environments, sets, types, strings are all modeled as functions.
  • Functions are records with infinite many keys.
  • Full unification still a work in progress.

Metaprogramming

  • Homoiconic syntax allows for powerful and simple macro system.
  • Abstract away boiler-plate, cost free.
  • Customize syntax to extend language with new features to fit your needs.
  • Shape the language to meet your problem, not the other way around.

Quoted expressions

  • Quote code expressions to avoid (or delay) evaluation.
  • Manipulate code like data.
  • Quasiquote enables selective unquoting of the code to evaluate parts.

Literate Programming

  • Write documentation directly inside an eevo script and convert it to Markdown.
  • Keep documentation local to ensure it stays up to date.

Tail call optimization

  • Recursive loops become computationally equivalent to imperative loops.

Dyslexic friendly

  • Primarily designed by someone with dyslexia, who wrote the language, standard library, and documentation to be as easy as possible to read.

Anti-Features

Just like jazz, what is missing is often more insightful:

No mutations

  • Model change only one way: function calls.
  • Ensures code is easy to reason about locally.
  • Mutations make programs difficult to predict and harder to read, increasing the mental load of every line of code.
    • Given the same code and data you always get the same result.
  • Prevents the mistakes that come from half constructed values.
  • Leave mutations as an optimization performed by the compiler.
    • Allows for other easy optimizations such as automatic parallelization.
  • Removes circular references, making automatic reference counting easy.

No dependencies (eg LLVM)

  • Dependencies are just someone else’s code, which silently increase the surface error of potential bugs.
  • Only relies on a C compiler and libc.

No statements

  • Everything is an expression: 5, "hello", def, if, etc.

No keywords

  • All symbols enjoy equal status and allows redefining them at will.
  • Modify the core language just like any users’ code.

No reader macros

  • Limit the amount of the language that authors can modify.
  • Ensures all scripts remain easy to read once you learn eevo.

No exceptions

  • Errors are just regular values which have to be explicitly handled.

No multiple return values

  • Just return a list, and require callee to explicitly expand into multiple values.

No explicit return

  • Last item of procedure is always returned.
  • Use Void to explicitly avoid returning last value.

No arrays, linked lists, or tuples

  • Just pairs (2-tuples) and records.
  • Construct lists, trees, or any other compound data structure out of pairs.

No function currying

  • Partial application should be explicit to avoid hard to debug accidents when you forget an argument.
  • Functions only take one argument, but it is often a list of arguments.
  • You are welcome to write functions in the curry style, but the standard library is not written that way.

No build systems

  • Simply run the primary .evo file (by convention the same name as the project) and let it handle including and running all other files as needed.

No mandatory editor tools

No garbage collector

  • Memory managed through a simple bump allocator, with reference counting in the works.

Coming Soon…

Automatic reference counting memory management

Strong static typing with type inference

Batteries included standard library

Powerful string interpolation

First class algebraic pattern matching

Improve error messages

Sandboxed

Full Unicode support

Interoperability

WebAssembly compiler

Environmental image

Hygienic macros

Multithreading

Optimizations