Skip to main content

Mo - Modern, Expressive, Fast Programming Language

Project description

Mo Language

Mo is a lightweight, dynamically-typed scripting language with a clean syntax, a bytecode compiler, and a growing standard library.

🚀 v0.4.0: C++ VM Optimizations Enabled!

  • NaN Boxing - 60% less memory, 2-5x faster
  • Inline Caching - 3-15x faster property access
  • Generational GC - 90% less pause time
  • Register VM - 30-50% fewer instructions

Check out mo_cpp/ for the high-performance C++ VM.
See C++ README for details.

fn greet(name) {
    print("Hello, " + name + "!")
}

greet("world")

Installation

pip install mo-language

After installing, use the mo command:

mo program.mo

Windows users: If mo is not found after install, add Python's Scripts folder to your PATH.
Mac/Linux users: If mo is not found, run the command the installer prints.

Language Guide

Variables

let x = 42
let name = "Mo"
let flag = true
let nothing = null

Reassign with = (no let):

x = x + 1

Types

Type Example
Number 3.14, 100
String "hello"
Bool true, false
Null null
List [1, 2, 3]
Dict {"key": "value"}

Operators

1 + 2        # arithmetic: + - * /
x == y       # equality: == !=
x < y        # comparison: < > <= >=
true && false  # logical: && ||
!true          # not

String concatenation uses +:

let msg = "Hello, " + "world"

Control Flow

if x > 0 {
    print("positive")
} else if x < 0 {
    print("negative")
} else {
    print("zero")
}
let i = 0
while i < 5 {
    print(i)
    i = i + 1
}
for item in [1, 2, 3] {
    print(item)
}

Functions

fn add(a, b) {
    return a + b
}

let result = add(3, 4)   # 7

Functions are first-class values:

let double = fn(x) { return x * 2 }

Lists

let nums = [10, 20, 30]
print(nums[0])          # 10
push(nums, 40)          # append
let last = pop(nums)    # remove last
print(len(nums))        # 3

Dicts

let user = {"name": "Alice", "age": 30}
print(user["name"])     # Alice
user["age"] = 31

for k in keys(user) {
    print(k + ": " + str(user[k]))
}

Dict keys can also be accessed with .:

print(user.name)
user.age = 32

Classes

class Animal {
    fn init(name) {
        self.name = name
    }
    fn speak() {
        print(self.name + " makes a sound")
    }
}

class Dog extends Animal {
    fn speak() {
        print(self.name + " barks")
    }
}

let d = Dog("Rex")
d.speak()   # Rex barks

Error Handling

try {
    throw "something went wrong"
} catch e {
    print("Caught: " + e)
}

Imports

import "std/math"
print(math_sqrt(16))   # 4.0

Standard Library

All stdlib modules are imported with import "std/<name>".

std/math

import "std/math"

math_sqrt(x)      # square root
math_pow(x, n)    # power
math_abs(x)       # absolute value
math_floor(x)     # floor
math_ceil(x)      # ceiling
math_round(x)     # round
math_min(a, b)    # minimum
math_max(a, b)    # maximum
math_log(x)       # natural log
math_sin(x)       # sine (radians)
math_cos(x)       # cosine
math_tan(x)       # tangent
math_pi()         # π ≈ 3.14159

std/random

import "std/random"

random_int(1, 10)      # random integer in [min, max]
random_float()         # random float in [0, 1)
random_pick([1,2,3])   # random element from list

std/time

import "std/time"

time_now()              # Unix timestamp (float)
time_ms()               # milliseconds since epoch
time_sleep(1.5)         # sleep for N seconds
time_format(ts, fmt)    # format timestamp, e.g. "%Y-%m-%d"
time_str(ts)            # ISO date string

std/json

import "std/json"

json_parse('{"a": 1}')      # string → dict/list
json_stringify(obj)          # dict/list → string
json_pretty(obj)             # pretty-printed string

std/file

import "std/file"

read("file.txt")             # read file as string
write("file.txt", content)   # write string to file (overwrite)
append("file.txt", content)  # append to file
exists("file.txt")           # true/false
delete_file("file.txt")      # delete file
list_dir(".")                # list directory → list of names

std/http

Requires no extra packages (uses Python's built-in http.server).

import "std/http"

serve(8080, fn(req) {
    return text("Hello, " + req.path)
})

Helper response builders:

text(body)           # 200 text/plain
html(body)           # 200 text/html
json_resp(data)      # 200 application/json
redirect(url)        # 302
not_found()          # 404
bad_request(msg)     # 400
error(msg)           # 500

HTTP client:

let res = fetch("https://example.com/api")
let res = fetch_post("https://example.com/api", json_stringify(data))

std/os

import "std/os"

os_name()        # "posix" or "nt"
os_cwd()         # current working directory
os_home()        # home directory
os_env("PATH")   # environment variable value
os_cpus()        # number of CPU cores

std/path

import "std/path"

path_join("dir", "file.txt")   # join path segments
path_dir("/a/b/c.txt")         # "/a/b"
path_base("/a/b/c.txt")        # "c.txt"
path_ext("/a/b/c.txt")         # ".txt"
path_abs("relative.txt")       # absolute path

std/url

import "std/url"

url_parse("https://example.com/p?q=1")   # dict with host, path, query, …
url_encode("hello world")                 # "hello+world"
url_decode("hello+world")                 # "hello world"

std/process

import "std/process"

proc_args()        # list of command-line arguments
proc_pid()         # current process ID
proc_exit(0)       # exit with code
proc_env("HOME")   # environment variable (alias for os_env)

std/crypto

import "std/crypto"

crypto_md5("hello")      # hex digest string
crypto_sha1("hello")     # hex digest string
crypto_sha256("hello")   # hex digest string

Built-in Functions

Function Description
print(x) Print value
len(x) Length of string/list/dict
str(x) Convert to string
num(x) Convert to number
type(x) Type name string
range(n) / range(a,b) List of integers
push(list, val) Append to list
pop(list) Remove and return last element
keys(dict) List of dict keys
has(dict, key) True if key exists
delete(dict, key) Remove key from dict
input(prompt) Read line from stdin
floor(x) Floor
ceil(x) Ceil
round(x) Round
abs(x) Absolute value

Testing

Run pytest Suite (Recommended)

pip install pytest
pytest tests/test_basic.py -v

The pytest suite covers core language features:

  • Variables, operators, functions
  • Lists, control flow (if/while/for)
  • Exceptions (try/catch/throw)
  • Built-in functions

Run Python Test Runner

python tests/test_runner.py          # run all tests
python tests/test_runner.py -v       # verbose mode
python tests/test_runner.py test.mo   # run specific file

The test runner discovers .mo test files in tests/, runs them with mo, and checks exit code.

Run Mo Test Files Directly

mo tests/run_tests.mo

Note: Some test files may have parser compatibility issues with newer language features.

Example test metadata file (tests/foo.mo.meta.json):

{
  "exit_code": 0,
  "output": "42"
}

CLI Reference

mo program.mo           # run with bytecode VM (default)
mo --interp program.mo  # run with tree-walk interpreter
mo --dis program.mo     # disassemble bytecode
mo                      # interactive REPL

Requirements

  • Python 3.9+
  • No external dependencies (stdlib only)

std/http fetch functions use urllib (built-in). For advanced HTTP needs, install requests separately.


Advanced Features

Type System

let x: int = 42          # type annotation
let y = 10  # int         # type comment

is_number(x)              # check type
is_string(x)
is_bool(x)
is_list(x)
is_dict(x)

cast(x, "string")         # type cast

std/regex

import "std/regex"

regex_match("^[a-z]+", "hello")   # true/false
regex_replace("cat", "the cat sat", "dog")  # "the dog sat"
regex_split("\\s+", "a b c")    # ["a", "b", "c"]

std/sqlite

import "std/sqlite"

let db = sqlite_open("data.db")
let rows = sqlite_exec(db, "SELECT * FROM users WHERE age > ?", [18])

for row in rows {
    print(row["name"])
}

sqlite_close(db)

std/yaml

import "std/yaml"

yaml_parse("key: value")       # string → dict
yaml_stringify({"key": "val"}) # dict → string

std/xml

import "std/xml"

xml_parse("<root><item>text</item></root>")  # string → element
xml_to_string(elem)                     # element → string

std/csv

import "std/csv"

csv_read("data.csv")                  # list of dicts
csv_write("output.csv", [{"a": "1"}])  # write list of dicts

std/net

import "std/net"

let sock = net_listen(8080)

while true {
    let conn = net_accept(sock)
    let data = net_recv(conn)
    net_send(conn, "HTTP/1.0 200 OK\r\n\r\nHello")
    net_close(conn)
}

std/gui

GUI module using Python's tkinter (requires pip install pillow for images).

import "std/gui"

let win = window("My Game", 800, 600)

rectangle(100, 100, 50, 50, "#00ff00")
circle(300, 200, 30, "#ff0000")
text(100, 160, "Player", 16, "#ffffff")
line(0, 0, 800, 600, "#888888")

on_click(fn(pos) {
    print("Clicked at: " + str(pos))
})

on_key(fn(key) {
    print("Pressed: " + key)
})

loop()

std/audio

import "std/audio"

audio_play("sound.mp3")

Package Manager

Mo has a package ecosystem for sharing reusable modules.

Search packages

mo search redis
mo search http

Install packages

mo install user/repo           # from GitHub
mo install user/repo@v1.0.0    # specific version
mo install https://example.com/foo.mo  # direct URL

List installed packages

mo list

Remove a package

mo remove <package-name>

Publish a package

mo publish

See mo publish for detailed publishing instructions.


LSP (Language Server Protocol)

Mo includes an LSP server for IDE editor support (hover, completion, diagnostics).

Start LSP Server

mo lsp                    # Start via stdio
mo lsp --stdio            # Explicit stdio mode
mo lsp --tcp --port 8765  # TCP mode on port 8765

VS Code Extension

A VS Code extension scaffold is provided in mo-vlang/:

  • package.json - VS Code extension configuration
  • syntaxes/mo.tmLanguage.json - Syntax highlighting
  • src/extension.ts - LSP client

To install the extension:

cd mo-vlang
npm install
code .
# Press F5 to run the extension in development mode

Supported Features

  • Hover: Hover over variables to see their type
  • Completion: Auto-complete keywords and symbols
  • Diagnostics: Real-time syntax error reporting

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mo_language-0.4.0-cp39-cp39-macosx_10_9_universal2.whl (180.8 kB view details)

Uploaded CPython 3.9macOS 10.9+ universal2 (ARM64, x86-64)

File details

Details for the file mo_language-0.4.0-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for mo_language-0.4.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 6cf472f76ba61b081a3f8b6781cc80c14ff10f7d8a4846df8d507eea537e96a8
MD5 00342b7a0e3b10a3c15ae4ee650c44a7
BLAKE2b-256 eea5da8a7179c8ec287d60f38a1b5cc08d8aa5fa1c147698f19a2ff33768f650

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page