Author: Chris M. Perez
Status: Academic Research Prototype
Disclaimer — Transparency About AI Usage The initial drafts of Solis—including documentation, prototypes, and parts of the compiler—were created with the help of AI tools following my prompts and design instructions. I do not claim to have written every line manually; instead, I guided the process, refined the output, and made the architectural and conceptual decisions. This repository represents an AI-assisted research prototype, not a fully hand-coded language implementation.
Solis is a functional programming language inspired by Haskell, combining Hindley-Milner type inference with bidirectional type checking concepts from Lean. The language features pattern matching, call-by-need evaluation, and monadic do-notation. The implementation includes an interactive REPL and dual backends: an interpreter and an LLVM-based code generator.
Solis draws inspiration from Haskell's lazy evaluation, monadic do-notation, and pattern matching, while incorporating bidirectional type checking concepts from Lean and Agda. The type system uses Hindley-Milner inference (Damas-Milner algorithm) with constraint generation and unification as the foundation, extended with bidirectional checking modes (synthesis and checking) for improved type inference in certain contexts.
The type system infers types across function boundaries without requiring explicit annotations while maintaining static type safety. Type schemes with universal quantification enable polymorphic functions. The bidirectional extension allows checking expressions against expected types, improving inference for lambda expressions and applications.
The compiler architecture separates parsing, type checking, and code generation into modular components sharing a common AST representation. This design allows the interpreter and LLVM backend to share the same frontend, enabling rapid iteration during development and optimized native code generation.
Lazy evaluation follows Haskell's call-by-need semantics, implemented via thunks with memoization. The ThunkValue structure caches computed results, enabling infinite data structures. The expression-oriented syntax with pattern matching supports algebraic data types, records, and monadic do-notation similar to Haskell's monad syntax.
Solis is an academic research project exploring type system implementation and compiler construction. The goal is to bridge theoretical foundations with practical implementation, producing a language suitable for real-world development.
The compiler architecture emphasizes modularity: lexer, parser, type checker, and code generators are separate components sharing a common AST representation. The LLVM backend generates optimized native code with runtime support for thunks, closures, and garbage collection. The interpreter enables rapid iteration during development with the same type system and language semantics.
The goal is to evolve Solis from an academic research project into a practical language capable of building real-world software.
See ROADMAP.md for detailed plans.
Language documentation and examples are in the doc/ directory. The doc/examples/ folder contains runnable examples organized by concept: functions, pattern matching, lists, records, algebraic data types, lazy evaluation, do notation, type inference, BigInt, and higher-order functions.
The Solis compiler provides several tools:
solis- Main compiler/interpreter with REPL supportsolis-lsp- Language Server Protocol implementation for IDE integrationsolisfmt- Code formatter for consistent code style
Solis includes an interactive REPL (Read-Eval-Print Loop) for rapid development and experimentation. Start the REPL with:
./solis repl
# or simply
./solisThe REPL provides built-in commands prefixed with ::
:help(or:h,:?) - Show available commands:type EXPRESSION(or:t) - Display the type of an expression:info IDENTIFIER(or:i) - Show information about a binding:browse [MODULE](or:b) - List all bindings in scope:kind TYPE(or:k) - Show the kind of a type:load FILE(or:l) - Load and execute a Solis file:reload- Reload the last loaded file:clear- Clear REPL state (limited, restart recommended for full reset):compile FILE- Compile a file to LLVM IR or native code:quit(or:q,:exit) - Exit the REPL
- History: Command history is saved to
~/.solis_historyand persists across sessions - Tab completion: Automatic completion for identifiers and commands
- Multi-line input: Automatically handles multi-line expressions (braces, brackets, parentheses)
- Type inference: Real-time type checking and inference feedback
- Prelude loaded: Standard library functions are available by default
REPL Configuration:
- History file:
~/.solis_history - Prelude: Automatically loaded on startup
- Module search paths: Configurable via
ModuleResolverwhen using the compiler programmatically
Formatter Configuration:
The solisfmt tool supports configuration options:
# Format files in-place (default)
./solisfmt file.solis
# Print formatted output to stdout
./solisfmt --stdout file.solis
# Minimal formatting (preserve operator spacing)
./solisfmt --minimal file.solis
# Quiet mode (suppress output messages)
./solisfmt --quiet file.solisFormatter options include:
- Indentation size (default: 2 spaces)
- Max line width (default: 80)
- Brace style (K&R or Allman)
- Operator spacing (configurable)
- Pattern arrow alignment
- Trailing comma handling
- Download a pre-built binary (when available)
- Build from source (see below)
A local VS Code extension is available for syntax highlighting and language icon support. This extension is not production-ready and must be installed locally from source.
To install locally:
cd vscode-solis
npm install
code --install-extension .The extension provides:
- Syntax highlighting for
.solisfiles - Language icon for Solis files in the file explorer
Note: This extension is not published to the VS Code marketplace and is intended for local development use only.
Ensure you have the required dependencies:
- C++ compiler with C++23 support (g++ or clang++)
- GMP development libraries (BigInt support)
- LLVM 21.x development libraries (code generation)
brew install gmp llvm@21sudo apt-get install libgmp-dev llvm-21-dev
# or on Fedora/RHEL:
sudo dnf install gmp-devel llvm21-develThen it is the standard Make build process:
makeThis produces three executables:
solis- Main compiler/interpretersolis-lsp- LSP serversolisfmt- Code formatter
You can build them individually:
make solis # Main compiler/interpreter
make solis-lsp # LSP server
make solisfmt # Code formatterTo install to a system location:
make installThis installs to /usr/local/bin by default. You can customize the installation prefix:
make install PREFIX=/custom/pathTo clean build artifacts:
make cleanIf you only need the interpreter without code generation capabilities, you can build without LLVM:
make solis NO_LLVM=1This produces a solis executable that can run Solis programs via the interpreter but cannot generate native code.
- C++ Compiler: g++ or clang++ with C++23 support
- GMP: GNU Multiple Precision Arithmetic Library (for BigInt support)
- LLVM: Version 21.x (optional, for code generation)
Standalone Makefile with automatic detection of LLVM and GMP installations. Searches common installation paths including Homebrew on macOS.
Solis is an academic research project. We welcome bug reports, feature suggestions, and contributions that align with the project's educational and research goals.
When contributing:
- Follow the existing code style and conventions
- Ensure all tests pass:
make test - Update documentation for new features
- Keep the focus on type system research and compiler implementation
MIT License - Copyright (c) 2025 Chris M. Perez