- Rust 85.7%
- Nix 14.3%
| lyt | ||
| nix | ||
| .envrc | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| readme.md | ||
lytlang
An experiment in programming languages.
Why?
Mostly for fun and learning purposes.
Also, I'm unnecessarily finnicky about syntax and how the code feels to read, write, navigate, and change. Maybe I should've got into a profession where I work more with my hands materially, but here we are!
I also care immensely about tooling. I greatly dislike having to include a dozen or more different files in the repository's root in order to make things work, though I do recognize that's largely due to so many tools needing to include some information in the repository!
I take a lot of inspiration from amazing projects such as Rust, Gleam, Deno, CoffeeScript, Elixir, Elm, Nix, and more.
Example
Here's what I envision the code might look like:
# comments start with pound because shebangs and stuff
# bind an identifier to a value
# it's not a variable because immutability is probably something I want by
# default, bindings are done with colons since we do that in json and yaml and
# kind of in Go and a few other places and I'm pretty sure I want to use = for
# pattern matching/equality like in Elixir
passing_score: 70
#: docstrings for the next thing are specified with "#:", comment+bind
good_score: 90
ten: add 3 7
nine: divide 27 3
eight: multiply 4 2
seven: subtract 10 3
# maybe colon is an infix special form/sugar for some bind function or macro?
# function are called without parentheses
# parentheses are only used for order-of-operations, so you _can_ include them
# optionally sort of as a side effect at least for single
four: square 2
sixteen: square(2)
# strings are single-quoted because it's one less keypress than double-quote
greeting: 'Hello, world!'
# you can escape as you might expect
farewell: 'See you at John\'s place!'
backslashes: 'Here are two backslashes: \\\\'
# multiline string literals with triple quotes
essay: '''People buy shoes at shoe stores.
People buy computers at computer stores.'''
# and if you need to put triple single quotes in your multiline string you can escape
essay: '''# code in a string!
\'''a multiline string literal\'''
'''
# write the greeting binding's value to stdout
# should output: Hello, world!
write stdout greeting
# or use print as a shortcut for `write stdout`
print greeting
###
multiline commands
may be specified
with triple hashes
###
###: Multiline docstrings work similarly, just add the colon
did I mention that functions are values and we want implicit returns?###
add: x y ! x + y
# here's an example of declaring the types... maybe?
add_i64_typed: x @i64 y@i64 !@i64 x + y
# feel free to add a newline and indent for longer function bodies
add_and_notify: x y !
print 'Adding some numbers!'
x + y
# define your own data structures
person: struct
name
age
# or on one line
person: struct name age
Symbols Summary
My thought process and hot take is that language concepts deserve symbols. Functions should be functions. This means no "operators" in the sense you would expect.
:to indicate a binding#to indicate a comment@to indicate a type!to indicate a function body.to access sub-items'to indicate a string?to indicate possibility of failure (and bubble failure up?)_is reserved for putting in identifiers and values
Goals & Justification
- General purpose programming language
- I'd like to be able to write web applications, games, command-line tools, tiny scripts, etc.
- Somehow don't converge on yet another lisp
- Not because lisp is bad or anything, I just want something somewhat original and to avoid parens
- Beautiful syntax (this is, of course, wildly subjective)
- Significant whitespace: we already format other languages structurally as if it were, why not actually do it and have less noise
- Use tabs for indentation and spaces to align
- Readable (reading and editing code is the bulk of my work)
- Strongishly typed
- I'm not willing to commit to a description or definition here yet, but I know I don't want a situation where I cannot restrict the type of something in order to prevent bugs and help ensure code changes work as expected and breaking changes aren't understandable
- Terse, small, or dense: I believe not having to read as much code means that code is easier to read and understand
- Familiar or otherwise immediately understandable to programmers
- Unambiguous
- This does not imply that the code should be self-describing, as part of my goal is that the tooling would assist with this. As an example, type-inference in the language and tools should be able to provide type hints in your editor, but not all identifiers should have to be explicitly typed
- Strongishly typed
- Writeable (writing code is not as important as being able to understand it, but it is still part of the process, and so is valuable to consider)
- Avoid using many symbols
- Avoid many keywords
- Avoid multiple ways of doing something
- Significant whitespace: we already format other languages structurally as if it were, why not actually do it and have less noise
- Generally "functional"
- First-class functions
- Projects should be able to be fully contained in a single file
- This would include dependencies and their locks
- Tools built-in
- Dependency management, language server, formatter, test runner, etc.
Non-Goals & Justification
- Performance
- Computers are plenty fast enough to interpret my nonsense language and do what simple things I would want
- That's not to say I don't care about performance, it's just secondary to the other goals of this project
Questions
- Do functions curry automatically like Elm/Haskell?
- Do I need tuples? Are they meaningfully different from lists/arrays if lists/arrays can contain different types?
- I'm guessing arrays are "similar" (each element is the same type)