eevo
Everything should be as simple as possible, but not simpler
- Albert Einstein
eevo is a high-level scripting language centered around functional records for data oriented programming, packaged in an simple and easy to use form factor.
- Simple: built on only a few concepts, which compose to construct powerful programs. Keeping it simple allows it stay hackable
- Small: extremely lightweight with less than 100KB sized binary, 2k lines of C99 code, and 1k semicolons
- Sweet: syntactic sugar for readable and easy syntax, built a top of invisible s-expressions
- Symmetric: Unification of many ideas and used with uniform syntax. Same principals and syntax are applied universally. Expressions outputted are always valid input to the same value.
- Symbolic: symbols are first class citizens
- Separable: modular design allows you to use only what you need, or modify each component to suit your needs
- Script-able: Clean and simple syntax encourages short and to the point code, and enables use as a shell
def fib(n)
"Fibonacci number of n"
if n < 2
n
fib(n - 1) + fib(n - 2)
fib 25
eevo can either be used to write short standalone modular scripts (do one thing and do it well), or be embedded in a larger program to enable high level hackable logic. This allows for a “middle out” approach where you can slowly replace low level code in existing code based with high level scripts (lua style), or out-source computationally expensive code to low level libraries (python approach). Both methods can be done at the same time with different languages, allowing eevo to glue different libraries, ecosystems, and tools together.
A lightweight module core allows you to choose how much of the language you need for your application, this comes in a few layers:
- Reading/Printing: Parse eevo code and output data structures unevaluated (eg config or data files)
- Evaluating: Simplify expressions
- Core: Procedures fundamental to evaluation (eg flow control, list manipulation, basic math)
- Standard Library: Additional procedures needed for many operations (eg IO, math, doc)
- Contrib: Officially sponsored community libraries and scripts
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
Functional programming
- All you need is data and functions to transform that data
Records as universal type
- Lists, functions, dictionaries, types, strings are all modeled as records
Interactive
- Read, Evaluate, Print, Loop (REPL)
Metaprogramming
- Homoiconic syntax allows for powerful and simple macro system, abstracting away boiler-plate
Quoted expressions
- Quasiquote and unquote
Types
- Numbers: integers
Int
, decimalsDec
, ratiosRatio
- Booleans: True, Nil
- Text: strings, symbols
- Lists, pairs
- Records
- Void
First class citizens
- Functions, with closures
- Anonymous functions (lambda calculus)
- Symbols (identifiers/variables)
- Macros, functions which transform code
- Environments (namespaces/modules/capabilities)
- Types
- Errors
Immutable
- Removes cognitive burden of thinking about the active state, and the bugs that come from it
- Prevents the mistakes that come from half constructed values
- Allows for easy optimizations such as automatic parallelization and make cyclic references impossible (removing the main downside of reference counting)
Tail call optimization
- Recursive loops become computationally equivalent to imperative loops
Anti-Features
Just like jazz, it is often more useful to see what is missing:
No statements
- Everything is an expression (
5
,"hello"
,def
,if
, etc)
No keywords
- All symbols are equal and can be redefined at will
No mutability
- TODO
- Removes circular and self referential objects, making automatic reference counting easy.
No reader macros
- TODO
- Should be easy to read anyone’s eevo scripts
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
No function currying
- Functions only take one argument, which is often a list of one or more function arguments
No garbage collector
- Memory is managed through reference counting
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 (eg paredit)
- Syntax should be easy to modify without specialized tools
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
WIP
Automatic reference counting memory management
Strong static typing with type inference
- First class
- Algebraic types (sum, product, exponential)
- Physical units
- Uncertainty
- Polymorphism
- Refinement types
- Codata
- Type holes
Batteries included standard library
- While still being minimal and orthogonal
Improved error messages
Interoperability with any programming language with C bindings
- WASM, C, Lisp, Python, Lua, Rust, Go, shell, etc
First class algebraic pattern matching
Powerful string interpolation
- templater (eg mustache, handlebars)
- unformat
- regex alternative
WebAssembly compiler
- Web interface, environment, and REPL
Environmental image
- Restore the environment exactly how you left it.
Hygienic macros
- Simple without need for
syntax-rules
orgensym
, similar to s7
Multithreading
Managed effects
- Control effects through capabilites via first class environments
Optimizations
- Auto parallelism
- GPU acceleration
- Opportunistic in place mutation
- Total pre-computation
- Constant folding and propagation
- Anything that can be computed at compile time will be
- Memorization (cache)