Welcome to Ferret! Ferret is a statically typed, beginner-friendly programming language designed to bring clarity, simplicity, and expressiveness to developers. With a focus on readability and a clean syntax, Ferret makes it easier to write clear, maintainable code while embracing modern programming principles.
-
Clone the repository:
git clone https://github.com/itsfuad/Ferret-Compiler.git cd Ferret-Compiler
-
Build the compiler:
cd scripts ./build.sh # Linux/macOS/Git Bash ./build.bat # Windows CMD/PowerShell
-
Add the
bin
directory to your PATH environment variable to useferret
commands globally.
Download the Ferret Language Support Extension for your IDE for Syntax Highlighting Errors.
# Initialize in current directory
ferret init
# Initialize in specific directory
ferret init /path/to/project
This creates a fer.ret
configuration file with default settings.
ferret
Ferret - A statically typed, beginner-friendly programming language
USAGE:
ferret run [options] Run project using entry point from fer.ret
MODULE MANAGEMENT:
ferret init [path] Initialize a new Ferret project
ferret get <module> Install a module dependency
ferret update [module] Update module(s) to latest version
ferret remove <module> Remove a module dependency
ferret list List all installed modules
ferret sniff Check for available module updates
ferret orphan List orphaned cached modules
ferret clean Remove unused module cache
OPTIONS:
-d, -debug Enable debug mode
NOTE: All flags support both single dash (-flag) and double dash (--flag) formats
EXAMPLES:
ferret run Run project using fer.ret configuration
ferret run -debug Run with debug output
ferret run --debug Run with debug output (alternative)
ferret init my-project-name Create new project named my-project-name
ferret get github.com/user/module Install a module from GitHub
ferret update Update all modules
The fer.ret
file contains project-specific settings:
name = "your_project_name"
[compiler]
version = "0.0.1"
[build]
entry = "path/to/your/entry.fer"
output = "bin"
[cache]
path = ".ferret"
[remote]
enabled = true
share = false
[neighbor]
modulename = "../path/to/your/module"
[dependencies]
github.com/user/repo = "0.0.2"
Ferret provides a comprehensive module management system for handling dependencies with version control.
# Initialize in current directory
ferret init
# Initialize in specific directory
ferret init /path/to/project
# Install all dependencies from fer.ret
ferret get
# Install specific module
ferret get github.com/user/repo
# Install specific version
ferret get github.com/user/[email protected]
# Check which dependencies have updates available
ferret sniff
# Example output:
# 📦 github.com/user/repo: v1.0.0 → v1.2.0 (update available)
# âś… github.com/other/module: v2.1.0 (up to date)
# Update all dependencies to latest versions
ferret update
# Update specific module to latest version
ferret update github.com/user/repo
# List all dependencies (direct and transitive)
ferret list
# Remove a dependency
ferret remove github.com/user/repo
# See orphan modules
ferret orphan
# Clean up unused dependencies
ferret cleanup
Ferret follows a dependency-driven update strategy that ensures compatibility:
- Direct Dependencies: Only modules explicitly listed in
fer.ret
are updated by user commands - Transitive Dependencies: Automatically resolved to the exact versions specified by their parent modules
- Version Pinning: Transitive dependencies use their specified versions, not the latest available versions
# Your project uses [email protected]
# [email protected] depends on [email protected]
# [email protected] is available but won't be used
ferret sniff # Shows: "ModuleA: v1.0 → v1.2 (update available)"
ferret update # Updates ModuleA to v1.2
# If [email protected] uses [email protected], then ModuleB gets updated
# If [email protected] still uses [email protected], then ModuleB stays at v2.0
This prevents dependency hell by ensuring that modules are only updated to versions that are tested and compatible with their parent dependencies.
Enable remote module imports in fer.ret
:
[remote]
enabled = true # Allow downloading modules from GitHub
share = false # Whether to share your modules publicly
- Explicit Opt-in: Remote imports must be explicitly enabled
- Version Verification: All module versions are verified against GitHub releases
- Lockfile System: Exact dependency versions are tracked in
ferret.lock
- Cache Management: Downloaded modules are cached locally for faster builds
# Latest version
ferret get github.com/user/repo@latest
# Specific version
ferret get github.com/user/[email protected]
# Version without 'v' prefix (auto-detected)
ferret get github.com/user/[email protected]
myproject/
├── fer.ret # Project configuration
├── ferret.lock # Dependency lockfile (auto-generated)
├── .ferret/ # Cache directory
└── src/ # Your Ferret source files
The ferret.lock
file tracks:
- Exact versions of all dependencies (direct and transitive)
- Dependency relationships and usage tracking
- Cache paths and download metadata
- Generation timestamp and integrity checks
- Statically Typed: Strong typing ensures that errors are caught early, making your code more predictable and robust.
- Beginner-Friendly: Ferret's syntax is designed to be easy to read and understand, even for new developers.
- Expressive Code: With simple syntax and clear semantics, Ferret is made to be highly expressive without unnecessary complexity.
- First-Class Functions: Functions are treated as first-class citizens, enabling functional programming paradigms while maintaining simplicity.
- Clear Structs and Interfaces: Structs have methods and are used for simplicity, with implicit interface implementation for cleaner code.
- Advanced Module System: Comprehensive dependency management with version control, automated resolution, and secure remote module support.
- Developer-Friendly Tooling: Rich error reporting, debug mode, and comprehensive CLI commands for project management.
// Single variable with type inference
let x = 10;
let y: f32;
let myname: str = "John";
// Multiple variables with type
let p, q, r: i32, f32, str = 10, 20.0, "hello";
let p, q: i32, str = 10, "hello";
// Multiple variables with type inference
let p, q, r = 10, 20.0, "hello";
let p, q = 10, "hello";
// Assignments
x = 15; // Single variable
p, q = 10, "hello"; // Multiple variables
p, q, r = 10, 20.0, "hello"; // Multiple variables with different types
// Type aliases
type Integer i32;
type Text str;
// Arithmetic operators
a = (a + b) * c; // Basic arithmetic
x++; // Postfix increment
x--; // Postfix decrement
++x; // Prefix increment
--x; // Prefix decrement
// Assignment operators
a += b; // Add and assign
a -= b; // Subtract and assign
a *= b; // Multiply and assign
a /= b; // Divide and assign
a %= b; // Modulo and assign
// Type casting
let a: i32 = 10;
let b: f32 = a as f32; // Cast i32 to f32
The Ferret compiler follows a multi-stage compilation pipeline designed for maintainability and extensibility:
- Lexer: Converts source code into tokens for parsing
- Parser: Transforms tokens into an Abstract Syntax Tree (AST)
- AST: Represents the program structure in a tree format
- Collector: Gathers symbols and builds symbol tables for scope resolution
- Resolver: Resolves symbol references and validates module imports
- Type Checker: Performs type inference and validates type compatibility
- Code Generator: Translates the validated AST into target assembly code (currently x86-64)
- Basic syntax
- Tokenizer
- Parser
- Variable declaration and assignment
- Simple assignments
- Multiple assignments
- Expressions
- Unary operators
- Increment/Decrement operators
- Assignment operators
- Grouping
- Type aliases
- Arrays
- Array indexing
- Array assignment
- String indexing
- Array spreading
- Structs
- Anonymous structs
- Struct literals
- Struct field access
- Struct field assignment
- Methods
- Interfaces
- Functions
- Dead code elimination
- Function calls
- Function parameters
- Variadic parameters
- Function return values
- Annonymous functions
- Closures
- Conditionals
- Control flow analysis
- Loops (for, while)
- Switch statements
- Type casting
- Maps
- Range expressions
- Error handling
- Imports and modules
- Local imports
- Remote module imports (GitHub)
- Module dependency resolution
- Version management and lockfiles
- Dependency update detection
- Transitive dependency handling
- Module caching system
- Security controls for remote imports
- Nullable/optional types
- Generics
- Advanced code generation
- Rich error reporting
- Collector (Symbol collection and scope building)
- Resolver (Symbol resolution and reference binding)
- Type checking (Type inference and validation)
- Code generation (x86-64 assembly - basic implementation)
- Read dependency from config file
- Download dependencies from config file
- Download indirect dependencies
- Cache downloaded modules
- Update config file
- Update lockfile
- Update dependency
- Delete dependencies
- Check for updates
- Auto update
- Detect orphans
- Delete orphans
- Compiler version check for all modules
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
To work on the Ferret compiler:
-
Prerequisites: Go 1.19 or later
-
Clone the repository and navigate to the compiler directory
-
Run tests:
# Run all tests go test ./... # Run tests with verbose output go test -v ./... # Run specific test package go test ./cmd -v
-
Build and test locally:
# Build the compiler go build -o ferret cmd/main.go # Test with sample files ./ferret ../app/cmd/main.fer --debug
-
Run local CI checks (recommended before pushing):
# On Linux/macOS/Git Bash ./scripts/ci-check.sh # On Windows Command Prompt/PowerShell .\scripts\ci-check.bat
This script runs the same checks as the CI pipeline locally.
The project includes several convenience scripts in the scripts/
directory:
# Build the compiler
./scripts/build.sh # Linux/macOS/Git Bash
.\scripts\build.bat # Windows CMD/PowerShell
# Run tests with formatted output
./scripts/test.sh # Linux/macOS/Git Bash
.\scripts\test.bat # Windows CMD/PowerShell
# Format all code
./scripts/fmt.sh # Linux/macOS/Git Bash
.\scripts\fmt.bat # Windows CMD/PowerShell
# Quick test with sample file
./scripts/run.sh # Linux/macOS/Git Bash
.\scripts\run.bat # Windows CMD/PowerShell
# Full CI validation
./scripts/ci-check.sh # Linux/macOS/Git Bash
.\scripts\ci-check.bat # Windows CMD/PowerShell
See scripts/README.md
for detailed script documentation.
The project includes comprehensive tests for:
- CLI argument parsing
- Lexical analysis (tokenizer)
- Syntax parsing
- Type checking
- Semantic analysis
- Configuration management
Run the test suite before submitting contributions:
cd compiler
go test ./...
The project uses GitHub Actions for continuous integration and deployment:
-
CI Pipeline (
ci.yml
): Runs on all branches and pull requests- Executes all tests
- Checks code formatting with
gofmt
- Runs
go vet
for static analysis - Builds the compiler
-
Pull Request Validation (
pr.yml
): Additional checks for PRs to main- Comprehensive test suite
- Code formatting validation
- Security scanning with gosec
- CLI functionality testing
-
Release Pipeline (
release.yml
): Triggers on pushes to main branch- Runs full test suite and formatting checks
- Builds cross-platform binaries (Linux, Windows, macOS)
- Creates GitHub releases with auto-generated changelog
- Uploads compiled binaries as release assets
-
Auto-formatting (
format.yml
): Manual/scheduled code formatting- Can be triggered manually via GitHub Actions
- Automatically formats code using
gofmt
- Commits formatting changes if needed
- Push changes to main branch
- All tests must pass
- Code must be properly formatted
- Automated release created with version tag
- Binaries built for multiple platforms
- Release notes auto-generated from commits
This project is licensed under the Mozilla Public License 2.0 - see the LICENSE file for details.