ESC
Type to search...
S
Soli Docs

Modules

module MyModule
  def hello
    println("Hello from MyModule!")
  end
end

Import a module.

import MyModule from "./my_module.sl"

MyModule.hello()

Import specific members.

import { hello } from "./my_module.sl"

hello()

Organize code with exports, imports, classes, and module structure.

Export Declarations

export

Makes a function, class, or constant available to other modules.

# math.sl

# Private function (not exported)
def validate_number(n: Int) -> Bool
  n >= 0
end

# Exported functions
export def add(a: Int, b: Int) -> Int
  a + b
end

export def subtract(a: Int, b: Int) -> Int
  a - b
end

export def multiply(a: Int, b: Int) -> Int
  a * b
end

export def divide(a: Int, b: Int) -> Float
  if (b == 0)
    panic("Division by zero")
  end
  float(a) / float(b)
end

export def factorial(n: Int) -> Int
  if (n <= 1)
    return 1
  end
  n * factorial(n - 1)
end
Classes in Modules

Modules can contain classes, enabling organized domain-driven code structures.

# shapes.sl

module Shapes
  class Circle
    radius: Float

    new(radius: Float)
      this.radius = radius
    end

    def area -> Float
      3.14159 * this.radius * this.radius
    end

    def perimeter -> Float
      2 * 3.14159 * this.radius
    end
  end

  class Rectangle
    width: Float
    height: Float

    new(width: Float, height: Float)
      this.width = width
      this.height = height
    end

    def area -> Float
      this.width * this.height
    end

    def perimeter -> Float
      2 * (this.width + this.height)
    end
  end
end
Nested Classes in Modules

Modules can also contain nested classes using the :: pattern for domain organization.

# commerce.sl

module Commerce
  class Product
    name: String
    price: Float
    quantity: Int

    new(name: String, price: Float, quantity: Int)
      this.name = name
      this.price = price
      this.quantity = quantity
    end

    def in_stock -> Bool
      this.quantity > 0
    end

    def discounted(percent: Float) -> Float
      this.price * (1 - percent / 100)
    end
  end

  class Cart
    items: Product[]

    new
      this.items = []
    end

    def add(product: Product)
      this.items.push(product)
    end

    def total -> Float
      sum = 0.0
      for item in this.items
        sum = sum + item.price
      end
      sum
    end
  end
end
Importing Classes

Import classes from modules using named imports or module namespace.

# Import the Commerce module from commerce.sl
import Commerce from "./commerce.sl"

# Use classes from the module
book = new Commerce.Product("Soli Guide", 29.99, 10)
shirt = new Commerce.Product("T-Shirt", 19.99, 3)

println(book.in_stock())          # true
println(book.discounted(20.0))    # 23.992

cart = new Commerce.Cart()
cart.add(book)
cart.add(shirt)
println(cart.total())             # 49.98

Import Statements

import

Import functions and classes from other modules.

# Import all exports
import "./math.sl"
print(add(2, 3));        # 5
print(factorial(5));     # 120

# Named imports
import { add, multiply } from "./math.sl"
sum = add(1, 2);          # 3
product = multiply(3, 4); # 12

# Aliased imports
import { add as sum, multiply as times } from "./math.sl"
result = sum(10, 20);  # 30
doubled = times(5, 6); # 30

# Import everything with a namespace
import "./utils.sl" as utils
formatted = utils.format_date(DateTime.utc());

Project Structure

my-project/
├── soli.toml
├── src/
│   ├── main.sl
│   ├── config.sl
│   └── utils/
│       ├── mod.sl
│       ├── string.sl
│       ├── array.sl
│       └── datetime.sl
└── lib/
  └── math/
    ├── mod.sl
    ├── basic.sl
    └── advanced.sl

Package Configuration

[package]
name = "my-app"
version = "1.0.0"
description = "My awesome soli application"
main = "src/main.sl"
soli_version = "1.16.0"   # minimum Soli version required to run this project

[dependencies]
# Local dependency
utils = { path = "./lib/utils" }

[dev-dependencies]
test-utils = { path = "./tests/test-utils" }

[scripts]
dev = "soli serve"
build = "soli build --release"
test = "soli test"

The optional soli_version field declares the minimum Soli interpreter version the project needs — the same idea as Cargo's rust-version (MSRV). When it is set, soli serve, soli test, and running a script inside the project refuse to start on an older soli and print an upgrade message. It is a bare minimum: a running version equal to or newer than the declared one passes. Omit the field to accept any Soli version.

Use Keyword

use

Alternative syntax for importing (alias for import).

use "./math.sl"
use { add, multiply } from "./math.sl"
use "./utils.sl" as utils;