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.

🚀 NEW: C++ Implementation Available!
Check out mo_cpp/ for a high-performance C++ VM with 37,500x speedup over Python.
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 Distribution

mo_language-0.3.0.tar.gz (125.1 kB view details)

Uploaded Source

Built Distribution

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

mo_language-0.3.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.3.0.tar.gz.

File metadata

  • Download URL: mo_language-0.3.0.tar.gz
  • Upload date:
  • Size: 125.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for mo_language-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d9ed4961d3970cb58c6f571843e380cd825f423a8fe5672e5f05ba039e35ea7c
MD5 ba1d26832d8292e52d312e8561990c34
BLAKE2b-256 99f575254092601e19cf2b2b47b30cdfc489c6ca5d11691ef37126988258665d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for mo_language-0.3.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 635442b553ce1db6679f68ad4dd1f04be1dfa46b259014a1c771a3abbe8847ef
MD5 4033f1d96e493600b139482283f8e181
BLAKE2b-256 83aa392bc1d9de47b1e501a9679a3177664110e8d903f5736878e9ae9be6c902

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