Skip to main content

A specialized scripting language for AI and Machine Learning.

Project description

Mlscript v1.0.0-beta — Documentation

Part I: Introduction to mlscript

1. Overview

mlscript is a high-level, dynamically-typed, object-oriented scripting language engineered for high-performance numerical computation and machine learning. Its design is centered around a sophisticated dual-nature architecture that combines the expressive power and rapid development capabilities of a scripting language with the computational efficiency of a compiled, low-level backend. This hybrid model is the cornerstone of the language, offering a unique blend of productivity and performance.

The frontend of mlscript is implemented in Python, providing a familiar, flexible, and feature-rich environment for developers.1 This layer is responsible for parsing the source code and managing the high-level execution logic, including a comprehensive object model with advanced features such as multiple inheritance governed by the C3 Method Resolution Order algorithm.1 This approach allows users to write clear, concise, and powerful code for complex tasks without sacrificing the dynamic nature expected of a modern scripting language.

The power of mlscript is fully realized through its C++ backend, which handles all performance-critical operations. This backend is built using a modern C++17 toolchain and leverages best-in-class libraries for numerical computing and parallelization.1 At its core is the

Tensor object, a multi-dimensional array implemented using the highly optimized Eigen linear algebra library.1 All numerical operations, from simple element-wise arithmetic to complex matrix multiplications, are delegated to this compiled C++ layer. Furthermore, the backend is parallelized using OpenMP, enabling

mlscript to take full advantage of multi-core processors to accelerate computationally intensive tasks.1

This deliberate separation of concerns allows mlscript to provide an optimal environment for machine learning research and development. The user-friendly frontend simplifies the process of defining models and algorithms, while the high-performance backend ensures that training and inference operations execute with the speed necessary for handling large-scale datasets. The entire system is seamlessly integrated, allowing developers to move effortlessly between high-level scripting and low-level numerical computation.

2. Getting Started

This section provides the necessary information to build the mlscript language module from source and prepare it for use in a development environment.

2.1. Prerequisites

To successfully build mlscript, the following dependencies must be installed and configured on the build system. The build process relies on CMake to manage dependencies and generate the appropriate build files for the target platform.1

  • C++17 Compliant Compiler: The mlscript C++ backend uses features from the C++17 standard. A modern compiler such as GCC, Clang, or MSVC that supports this standard is required.
  • CMake (Version 3.15 or higher): The project uses CMake for its build system automation. The minimum required version is 3.15.
  • Python and NumPy: A Python installation (including development headers) is necessary for building the Python bindings. The NumPy library is also required, as its C API headers are used for interoperability with the Tensor object. The build script will automatically locate the Python interpreter and NumPy include directories.
  • OpenMP: The language's C++ backend is designed for parallel execution and requires the OpenMP library. The CMake configuration will fail if OpenMP is not found on the system.
  • Eigen and pybind11: The source code for the Eigen and pybind11 libraries must be present within the third_party directory of the project's source tree. The build system is configured to compile these libraries directly from this location rather than relying on a system-wide installation.

2.2. Building from Source

The compilation process is managed by CMake and produces a Python extension module. This module can then be imported and used like any other Python package.

The build process can be summarized in the following steps:

  1. Obtain the Source Code: Clone or download the mlscript source code repository.

  2. Populate Dependencies: Ensure that the source code for Eigen and pybind11 is located in the third_party/eigen and third_party/pybind11 subdirectories, respectively.

  3. Configure the Build: Navigate to the root directory of the source code in a terminal and run CMake to generate the build files.
    Bash
    cmake.

  4. Compile the Module: Execute the build command. On Linux or macOS, this is typically done with make.
    Bash
    make

    Alternatively, the platform-agnostic CMake build command can be used:
    Bash
    cmake --build.

  5. Locate the Artifact: Upon successful compilation, the mlscript Python module (e.g., mlscript.so on Linux or mlscript.pyd on Windows) will be placed in the root source directory of the project.1 This is a deliberate configuration choice to make the module immediately available for use without requiring installation into a system or virtual environment directory.

Once built, the mlscript interpreter can be run, or the module can be imported into an interactive Python session from the project's root directory.

Part II: Language Fundamentals

3. Lexical Structure and Data Types

This section details the fundamental building blocks of the mlscript language, including its variable assignment rules and its set of primitive and compound data types.

3.1. Variables and Assignment

mlscript is a dynamically-typed language, meaning that the type of a variable is determined at runtime and does not need to be explicitly declared. Variables are created upon their first assignment. The assignment operation uses the single equals sign (=) operator.1

The left-hand side of an assignment must be a valid target, such as a variable name, an element of a collection (via index access), or an attribute of an object. The right-hand side can be any valid expression. The interpreter evaluates the right-hand side expression and binds its resulting value to the name on the left-hand side within the current scope.1

Example:

Code snippet

x = 10 // Assigns an integer to x
y = "hello" // Assigns a string to y
z = x + 5 // Assigns the result of an expression to z

3.2. Primitive Data Types

mlscript supports a standard set of primitive data types for representing numbers, boolean values, and text.

  • Numbers: The language recognizes both integer and floating-point numerical literals. These are parsed into Number nodes in the Abstract Syntax Tree (AST) and are handled as standard numerical types during execution.1
    • Integers: 1, 42, -100
    • Floats: 3.14, -0.01, 1.0e-5
  • Booleans: The boolean type has two literal values: true and false. These keywords are case-sensitive and are represented internally by BooleanLiteral nodes.1 They are used primarily in conditional logic.
  • Strings: String literals are sequences of characters enclosed in either single (') or double (") quotes. They are represented by StringLiteral nodes in the AST.1

3.3. Data Structures

mlscript provides built-in support for several versatile data structures, which are created as standard Python objects at runtime.1

  • Lists: A list is an ordered, mutable collection of items. List literals are defined by enclosing a comma-separated sequence of expressions in square brackets (``). The items in a list can be of any type.
    • AST Node: ListLiteral 1
    • Example: my_list = [1, "apple", true, ]
  • Dictionaries: A dictionary is an unordered collection of key-value pairs. Dictionary literals are defined using curly braces ({}), with each pair consisting of a key expression, a colon (:), and a value expression. Keys are typically strings or numbers.
    • AST Node: DictLiteral 1
    • Example: my_dict = {"name": "Alice", "age": 30}
  • Tuples: A tuple is an ordered, immutable collection of items. Tuple literals are formed by a comma-separated sequence of expressions, typically enclosed in parentheses (()). A single-element tuple must have a trailing comma (e.g., (5,)). An empty tuple is created with empty parentheses ().
    • AST Node: TupleLiteral 1
    • Example: my_tuple = (10, 20, "config")

4. Expressions and Operators

mlscript provides a rich set of operators for performing arithmetic, comparison, and membership checks. The order of evaluation for these operators is governed by a well-defined precedence hierarchy.

4.1. Arithmetic Operators

The language supports standard arithmetic operators for numerical computations. When used with Tensor objects, these operators perform element-wise operations delegated to the high-performance C++ backend.1

  • +: Addition. Also used for string concatenation.
  • -: Subtraction.
  • *: Multiplication.
  • /: Division.

The language also supports unary + and - operators for indicating the sign of a numerical literal or expression.1

4.2. Comparison and Membership Operators

These operators evaluate to a boolean value (true or false) and are primarily used in conditional statements.

  • Comparison Operators:
    • ==: Equal to
    • !=: Not equal to
    • <: Less than
    • <=: Less than or equal to
    • >: Greater than
    • >=: Greater than or equal to
  • Membership Operators:
    • in: Returns true if an element is found within a sequence.
    • not in: Returns true if an element is not found within a sequence.

The membership operators are supported for lists, strings, dictionaries (checking for key membership), and tuples.1

4.3. Operator Precedence

The precedence of operators determines the order in which they are evaluated in a complex expression. In mlscript, this hierarchy is not defined by an explicit table but is a natural consequence of the grammar's structure, which is implemented using a recursive descent parser.1 The parser's functions are called in a specific sequence (

comparison_expression -> expr -> term -> factor), which ensures that operators handled in later functions (like * and / in term) are evaluated before those in earlier functions (like + and - in expr).

The following table summarizes the operator precedence in mlscript, from highest to lowest.

Precedence Operator Description Associativity
Highest () Grouping N/A
. `` () Attribute Access, Indexing, Function Call Left-to-Right
- + Unary Minus, Unary Plus N/A
* / Multiplication, Division Left-to-Right
+ - Addition, Subtraction Left-to-Right
in not in Membership Left-to-Right
Lowest == != < > <= >= Comparisons Left-to-Right

5. Statements and Control Flow

mlscript provides a comprehensive set of control flow statements for directing the execution path of a program, including conditionals for decision-making and loops for repetitive tasks.

5.1. Conditional Execution: if-elif-else

Conditional logic is implemented using the if, elif (else if), and else keywords. The structure allows for branching execution based on the evaluation of one or more boolean expressions.

An if statement begins with a condition. If this condition evaluates to true, the associated block of code is executed. It can be followed by zero or more elif clauses, each with its own condition, which are tested sequentially if all preceding conditions were false. An optional else clause at the end provides a block of code to be executed if none of the if or elif conditions are met.1

Example:

Code snippet

x = 20
if (x < 10) {
print("x is less than 10")
} elif (x > 10) {
print("x is greater than 10")
} else {
print("x is exactly 10")
}

5.2. Loops: while and for...in

mlscript offers two primary looping constructs: while for condition-based iteration and for...in for iterating over sequences.

  • while loop: The while loop repeatedly executes a block of code as long as its condition remains true. The condition is checked before each iteration.1

    Example:
    Code snippet
    count = 0
    while (count < 5) {
    print(count)
    count = count + 1
    }

  • for...in loop: The for...in loop iterates over the elements of a sequence, assigning each element to a loop variable in turn. The language supports iteration over lists, strings, tuples, and range objects. Attempting to iterate over an unsupported type will result in a runtime error.1

    Example:
    Code snippet
    items = ["a", "b", "c"]
    for item in items {
    print(item)
    }

5.3. Loop Control: break and continue

The execution of loops can be controlled with the break and continue statements.

  • break: Immediately terminates the innermost enclosing while or for loop.
  • continue: Skips the remainder of the current iteration and proceeds to the next iteration of the innermost enclosing loop.

mlscript provides an important robustness feature related to these statements. The parser validates their usage during the parsing phase, before the code is ever executed. It maintains an internal state to track whether it is currently inside a loop body. If a break or continue statement is found outside of a while or for loop, the parser will immediately raise a SyntaxError.1 This provides immediate feedback to the developer about misplaced control statements, preventing a class of errors that would otherwise only appear at runtime.

6. Functions

Functions are fundamental, first-class objects in mlscript. They are used to encapsulate reusable blocks of code, promoting modularity and organization.

6.1. Function Definition and Calls

Functions are defined using the fun keyword, followed by the function name, a list of parameters in parentheses, and a block of code in curly braces.1

  • Parameters and Arguments: Functions can accept zero or more parameters. When the function is called, arguments are passed to these parameters.
  • Default Arguments: Parameters can be assigned a default value. If a caller does not provide an argument for a parameter with a default value, the default is used instead. A key syntactic rule, enforced by the parser, is that all parameters without default values must appear before any parameters that have default values.1
  • Return Values: The return statement is used to exit a function and optionally pass a value back to the caller. If a function reaches the end of its body without encountering a return statement, it implicitly returns a None value.1

Example:

Code snippet

fun greet(name, greeting = "Hello") {
return greeting + ", " + name + "!"
}

message = greet("World") // message is "Hello, World!"
message2 = greet("Alice", "Hi") // message2 is "Hi, Alice!"

6.2. Variable Scope

mlscript employs lexical (or static) scoping, which means that the scope of a variable is determined by its position within the source code. A variable defined inside a function is local to that function and is not accessible from the outside. A function can, however, access variables defined in its containing (enclosing) scopes.

This scoping mechanism is implemented through a scope_stack in the language's C++ evaluation engine.1 When a function is called, a new scope (a new map for storing variables) is pushed onto the stack. When a variable is accessed, the interpreter searches for it by starting with the topmost scope on the stack and working its way down through parent scopes until the variable is found or the global scope is reached. When the function returns, its scope is popped from the stack, and its local variables are destroyed.1 This robust implementation ensures that variable lifetimes are managed correctly and predictably.

Part III: Object-Oriented Programming

mlscript is a fully object-oriented language, providing a powerful and flexible class system for creating custom data types with associated behaviors. The object model supports key features such as inheritance, method overriding, and dynamic attribute access.

7.1. Classes and Instances

  • Class Definition: Classes are defined using the class keyword, followed by the class name and a body enclosed in curly braces ({}). The class body is where methods are defined.1 A notable design choice in
    mlscript is that class bodies are restricted to containing only method definitions (using the fun keyword). Unlike languages such as Python, mlscript does not permit class-level attributes or other arbitrary statements directly within the class body. Any attempt to include non-method statements will result in a SyntaxError during the parsing phase.1 This decision simplifies the object model by ensuring that all state is instance-level state, managed within the instance's methods.
  • Instance Creation: An instance of a class is created by calling the class as if it were a function, e.g., my_instance = MyClass().
  • The init Method: When an instance is created, mlscript automatically looks for a method named init. If this method exists, it is called immediately after the instance is created, and any arguments passed during instantiation are forwarded to it. The init method serves as the class constructor and is the primary place to initialize the instance's state (its attributes).1

Example:

Code snippet

class Dog {
fun init(name, age) {
self.name = name
self.age = age
}
}

my_dog = Dog("Rex", 5)
print(my_dog.name) // Prints "Rex"

7.2. Attributes and Methods

  • Methods: Methods are functions defined inside a class. The first parameter of every method is a reference to the instance on which the method is being called. By convention, this parameter is named self.1
  • Attributes: Attributes are variables that belong to an instance. They are created, accessed, and modified using dot notation (e.g., instance.attribute). Attributes are typically created within the init method by assigning to self, but they can also be created in other methods. They are stored in a dictionary unique to each instance.1

Example:

Code snippet

class Counter {
fun init() {
self.value = 0
}

fun increment() {  
    self.value \= self.value \+ 1  
}

fun get\_value() {  
    return self.value  
}  

}

c = Counter()
c.increment()
c.increment()
print(c.get_value()) // Prints 2

7.3. Inheritance

mlscript supports both single and multiple inheritance, allowing a class (the child class) to inherit methods from one or more other classes (the parent classes). Inheritance is specified using the inherits keyword after the class name.1

When a method is called on an instance, mlscript first searches for the method in the instance's own class. If it is not found, it searches through the parent classes in a specific, well-defined order. This search order is known as the Method Resolution Order (MRO). mlscript implements the same sophisticated C3 linearization algorithm for its MRO as Python.1 This ensures that in complex multiple inheritance hierarchies, the order in which methods are resolved is consistent, predictable, and avoids common pitfalls.

Example:

Code snippet

class Animal {
fun speak() {
print("The animal makes a sound")
}
}

class Cat inherits Animal {
fun speak() {
print("Meow")
}
}

c = Cat()
c.speak() // Prints "Meow"

7.4. Accessing Superclass Methods: super()

Within a method of a child class, it is often necessary to call the implementation of that same method from its parent class. This is achieved using the super() keyword. A call like super().method_name() will invoke the version of method_name found in the next class in the MRO.1

The implementation of super() in mlscript is robust and correctly handles complex inheritance scenarios. The interpreter maintains a method_context_stack that tracks the current instance (self) and the class where the currently executing method was defined. When super() is called, the interpreter uses this context to look up the instance's MRO, find the defining class, and then start its search for the method in the next class in the MRO.1 This ensures that

super() always does the right thing, even with multiple levels of inheritance or diamond-shaped inheritance patterns. Using super() outside of a class method will result in a runtime error.

Example:

Code snippet

class Person {
fun init(name) {
self.name = name
}
}

class Employee inherits Person {
fun init(name, employee_id) {
super().init(name) // Calls Person's init method
self.employee_id = employee_id
}
}

e = Employee("Jane Doe", 12345)
print(e.name) // Prints "Jane Doe"
print(e.employee_id) // Prints 12345

Part IV: Advanced Features

mlscript includes several advanced features that provide powerful mechanisms for error handling, resource management, and interoperability with the broader Python ecosystem.

8.1. Error Handling: try-catch-finally

mlscript provides a structured exception handling mechanism similar to that of other modern languages, using try, catch, finally, and throw keywords.

  • try: A try block encloses a section of code where an exception might occur.
  • catch (e): If an exception is thrown within the try block, execution immediately jumps to the corresponding catch block. The exception object that was thrown is bound to the variable specified in the parentheses (e.g., e).
  • finally: An optional finally block contains cleanup code that is guaranteed to execute after the try and catch blocks, regardless of whether an exception was thrown or caught.
  • throw: The throw statement is used to raise an exception. Any expression can be thrown as an exception value.

The interpreter implements this control flow using a custom MlscriptThrow exception internally. When a throw statement is executed, this exception is raised. The visit_TryCatch method then uses a standard try...except...finally structure to catch this signal, execute the catch block if present, and ensure the finally block is always executed.1

Example:

Code snippet

fun divide(a, b) {
if (b == 0) {
throw "Division by zero error"
}
return a / b
}

try {
result = divide(10, 0)
print("Result:", result)
} catch (error) {
print("Caught an exception:", error)
} finally {
print("Execution finished.")
}

8.2. Context Management: with

The with statement provides a convenient way to manage resources, ensuring that setup and teardown operations are always performed correctly. It simplifies the pattern of try...finally for resource management.

To be used with a with statement, an object must implement the context management protocol, which consists of two special methods:

  • __enter__(): This method is called when execution enters the with block. Its return value is optionally assigned to a variable if the as keyword is used.
  • __exit__(): This method is called when execution leaves the with block, either normally or due to an exception. It is responsible for releasing the resource.

The mlscript interpreter enforces this protocol at runtime, checking for the existence of __enter__ and __exit__ methods on the context object and calling them at the appropriate times.1 This feature is particularly important for the built-in

no_grad context manager.

8.3. Interoperability: import

mlscript provides a powerful and direct bridge to the vast ecosystem of Python libraries through its import statement. This allows developers to leverage existing Python code and packages for tasks that are not part of the mlscript core language, such as data visualization, file I/O, or web requests.

The syntax for importing is fixed: import <module_name> as <alias>. The module name must be a string literal, and an alias is required.1 At runtime, the interpreter uses Python's standard

importlib.import_module function to dynamically load the specified Python module. The imported module object is then bound to the specified alias name in the current mlscript scope, making its functions and classes available for use.1

Example:

Code snippet

import "numpy" as np

// Create a NumPy array using the imported module
a = np.array()

// Pass the NumPy array to the mlscript tensor constructor
t = tensor(a)

print(t)

Part V: The Core Numerical Engine

The heart of mlscript is its high-performance numerical engine, implemented in C++ and exposed to the scripting environment. This engine is centered around the Tensor object and a sophisticated automatic differentiation system.

9. The Tensor Object

9.1. Introduction

The Tensor is the central data structure for all numerical computation in mlscript. It represents a two-dimensional matrix of double-precision floating-point numbers. For maximum performance, the Tensor is not a pure script-level object; it is a C++ class that uses the highly optimized Eigen::Matrix library for its underlying data storage and mathematical operations.1 The interface to this powerful C++ object is exposed to the

mlscript environment via the pybind11 library, ensuring seamless and efficient interaction between the scripting frontend and the numerical backend.1

Beyond being a simple matrix, every Tensor object is also a potential node in a dynamically constructed computational graph, which is the foundation of mlscript's automatic differentiation capabilities.

9.2. Tensor Creation

Tensor objects can be created in two primary ways, providing flexibility and interoperability with other numerical libraries.

  • From mlscript Lists: The most direct way to create a Tensor is by calling the built-in tensor function with a nested list of numbers.
    Code snippet
    t1 = tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])

  • From NumPy Arrays: mlscript is designed for seamless interoperability with NumPy. A Tensor can be created directly from a 2D NumPy array. This conversion is highly efficient as it leverages the C-level APIs of both NumPy and pybind11.1
    Code snippet
    import "numpy" as np
    arr = np.ones((2, 3))
    t2 = tensor(arr)

9.3. Indexing and Slicing

mlscript provides a rich and expressive syntax for accessing and modifying Tensor data, supporting a wide range of indexing and slicing operations that mirror the capabilities of libraries like NumPy.1

  • Integer Indexing:
    • To access a single scalar value, provide a tuple of row and column indices: scalar = t[row, col].
    • To extract an entire row as a new 1xN Tensor, provide a single integer index: row_tensor = t[row]. Negative indexing is supported for rows, where -1 refers to the last row.
  • Slice Indexing:
    • Slicing is performed using the start:stop:step syntax. A slice can be used to select a range of rows: sliced_rows = t[1:3].
    • Slices can be combined with integer indices in a tuple to select sub-regions of the tensor. For example, t[0, 1:3] selects elements from the first row and columns 1 and 2. t[0:2, 0:2] selects a 2x2 sub-matrix from the top-left corner.

9.4. Tensor Operations

All operations on Tensor objects are executed by the underlying C++ engine, ensuring high performance.1

  • Element-wise Arithmetic: The standard arithmetic operators (+, -, *, /) perform element-wise operations when applied to two Tensor objects of the same dimensions.
  • Scalar Operations: A Tensor can be multiplied by a scalar value, which applies the operation to every element in the tensor (e.g., t * 2.0).
  • Matrix Multiplication: True matrix multiplication is performed using the built-in matmul function: result = matmul(t1, t2).
  • Reduction: The .sum() method reduces the tensor to a single 1x1 Tensor containing the sum of all its elements.

A critical performance feature of the Tensor object is its implementation of Python's buffer protocol.1 This allows other Python libraries, most notably NumPy, to access the

Tensor's underlying C++ memory buffer directly without needing to copy the data. This zero-copy interoperability is essential for efficient data exchange in numerical workflows, preventing memory bottlenecks when moving data between mlscript and the broader Python scientific computing stack. Furthermore, the C++ implementation of certain operations, such as slicing, is parallelized using OpenMP, allowing the language to leverage multiple CPU cores to accelerate data manipulation tasks.1

10. Automatic Differentiation

Automatic differentiation (AD) is a cornerstone feature of mlscript, enabling the automatic computation of gradients for complex functions. This is essential for training machine learning models using gradient-based optimization algorithms. mlscript implements a reverse-mode AD system based on the dynamic construction of a computational graph.

10.1. The Computational Graph

mlscript does not require users to pre-define a static graph. Instead, a computational graph is built dynamically, on-the-fly, as Tensor operations are executed. Every Tensor object stores pointers to its parent Tensors (the operands that created it) and the operation that was performed.1 For example, when

C = A + B is executed, a new Tensor C is created that holds references to A and B and stores the operation type "+". This chain of references forms a directed acyclic graph (DAG) that represents the exact sequence of computations performed.

This graph construction is conditional. It only occurs when gradient tracking is enabled. This allows users to switch off the overhead of graph building when it is not needed, such as during model inference.

10.2. Gradient Computation: .backward()

The process of computing gradients is initiated by calling the .backward() method on a Tensor. Typically, this is done on a scalar Tensor that represents the final output of a function, such as the loss of a machine learning model.

When .backward() is called, the C++ engine performs the following steps 1:

  1. Topological Sort: It traverses the computational graph backwards from the starting Tensor to build a topologically sorted list of all nodes (Tensors) involved in the computation. This ensures that when gradients are propagated, a node's gradient is fully computed before it is used to compute the gradients of its own parents.
  2. Gradient Initialization: The gradient of the starting Tensor with respect to itself is initialized to 1.
  3. Backpropagation: The engine iterates through the sorted list in reverse order. For each Tensor in the graph, it applies the chain rule based on the operation that created it. For example, for a matrix multiplication C = matmul(A, B), it uses the incoming gradient of C to compute the gradients for A and B and adds them to the .grad attributes of A and B. This process continues until gradients have been accumulated for all "leaf" nodes in the graph (the original input Tensors).

10.3. Inspecting Gradients: .grad

After .backward() has been called, the computed gradient for any Tensor t in the graph is stored in its .grad attribute. This attribute is exposed as a read-only property that returns the gradient as a NumPy array, making it easy to inspect or use with external Python libraries.1 The

.grad attribute of a Tensor has the same dimensions as the Tensor itself.

10.4. Inference Mode: no_grad

For performance-critical situations where gradients are not required (e.g., model inference or forward passes), mlscript provides the no_grad context manager. Any code executed within a with no_grad: block will not build the computational graph. This significantly reduces memory consumption and computational overhead.

This feature is implemented through a clean, cross-language mechanism. The Python-level NoGradManager object, when entering the with block, calls a method on the C++ Evaluator object. This C++ method toggles a global boolean flag within a singleton AutodiffContext object.1 Every

Tensor operation in the C++ backend first checks the state of this global flag before attempting to record its parents and operation in the computational graph.1 This design provides a simple and efficient way to control the behavior of the entire automatic differentiation engine from the script level.

Example of a full AD workflow:

Code snippet

// Create input tensors
a = tensor([[2.0]])
b = tensor([[3.0]])

// Perform computations (builds the graph)
c = a * b
d = c + a
e = d.sum()

// Compute gradients
e.backward()

// Inspect the gradients
print(a.grad) // Gradient of e with respect to a
print(b.grad) // Gradient of e with respect to b

// Perform inference without tracking gradients
with no_grad:
result = a * b // This operation is not added to the graph

Part VI: Reference

11. Built-in Functions and Objects

mlscript provides a set of globally available functions and objects that form its standard library. These built-ins are immediately available in any mlscript program without needing to be imported.

  • Functions:
    • len(object): Returns the length (number of items) of an object. Applicable to lists, strings, dictionaries, and tuples. This is a direct mapping to the Python len function.
    • range(...): Generates a sequence of numbers. It behaves identically to Python's range function.
    • min(...): Returns the smallest item from an iterable or the smallest of two or more arguments.
    • max(...): Returns the largest item from an iterable or the largest of two or more arguments.
    • sum(iterable): Returns the sum of all items in an iterable.
  • Objects and Factories:
    • tensor(data): The factory function/constructor for creating Tensor objects from nested lists or NumPy arrays.
    • matmul(t1, t2): A function that performs matrix multiplication on two Tensor objects. It is a convenient alias for the C++ backend's matmul implementation.
    • no_grad: The context manager instance used with the with statement to disable automatic differentiation.

12. Language Keywords

The following identifiers are reserved keywords in the mlscript language and cannot be used as variable, function, or class names.

Keyword Description
as Used with import to create an alias for a module.
break Exits the innermost loop.
catch Defines a block to handle exceptions thrown in a try block.
class Defines a new class.
continue Skips to the next iteration of the innermost loop.
elif Defines a conditional "else if" block in an if statement.
else Defines a block to execute when if/elif conditions are false.
false The boolean literal for false.
finally Defines a cleanup block that always executes after try/catch.
for Defines a loop for iterating over a sequence.
fun Defines a new function.
if Defines a block for conditional execution.
import Imports an external Python module.
in Used in for loops and for membership testing.
inherits Specifies parent classes in a class definition.
not Used with in for negative membership testing (not in).
print Prints a value to the console.
return Exits a function and returns a value.
super Accesses methods from a parent class.
throw Raises an exception.
true The boolean literal for true.
try Defines a block of code for exception handling.
while Defines a loop that executes as long as a condition is true.
with Used with context managers for resource management.

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 Distributions

mlscript_lang-0.9.0-cp312-cp312-win_amd64.whl (26.6 kB view details)

Uploaded CPython 3.12Windows x86-64

mlscript_lang-0.9.0-cp311-cp311-win_amd64.whl (26.6 kB view details)

Uploaded CPython 3.11Windows x86-64

mlscript_lang-0.9.0-cp310-cp310-win_amd64.whl (26.6 kB view details)

Uploaded CPython 3.10Windows x86-64

mlscript_lang-0.9.0-cp39-cp39-win_amd64.whl (26.6 kB view details)

Uploaded CPython 3.9Windows x86-64

mlscript_lang-0.9.0-cp38-cp38-win_amd64.whl (26.6 kB view details)

Uploaded CPython 3.8Windows x86-64

File details

Details for the file mlscript_lang-0.9.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for mlscript_lang-0.9.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 f411bfd4bb152ef5e324dcfd8b2ced05d88db8c76e7e6c33b32b95852485a38e
MD5 e730fdc179786886398af34677213c94
BLAKE2b-256 5a3c57c505c67f67677018cc2cd00dfac1f9c225b3f3ead8da01fc9cf640d9e7

See more details on using hashes here.

File details

Details for the file mlscript_lang-0.9.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for mlscript_lang-0.9.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 7d51ac4d7228485f6546ecf1dfaeca2e496614100704212d0b7279936edb700a
MD5 39be9fca6156dc3a9b3f37e9d230cc10
BLAKE2b-256 338bdd1d68f570eae3d1cceeeb1b56fed1e05370da2939fe1e1dfd739a6698aa

See more details on using hashes here.

File details

Details for the file mlscript_lang-0.9.0-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for mlscript_lang-0.9.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 416055b38b11a7f2d3cba804d6bf995bbf6baa50fd741bfa0f3d149254e5fded
MD5 f485475a2988b406a94babec9cc36a43
BLAKE2b-256 059b4ad54356b2f3cb5a044b5768db02520f715545998ac7cc13734ca4d05ee0

See more details on using hashes here.

File details

Details for the file mlscript_lang-0.9.0-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for mlscript_lang-0.9.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 18e0a1ff7f1e539fff1abdadab9880cd9b4b268259d2ca157affb05ed764d1f0
MD5 af43534dd53401dbe0fa4a2ed45a4133
BLAKE2b-256 8f235c015f26fb58b9fdfe28fa76f787bf231b530cd6437c5f376d4a37a4b9a6

See more details on using hashes here.

File details

Details for the file mlscript_lang-0.9.0-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for mlscript_lang-0.9.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 5fdd03eedd356d8a81a6f90868f7bc158da91f1d7cb54c87fb31111a4f3f6809
MD5 4c55e155ffd1d2aa06dbbf393edade7a
BLAKE2b-256 1d2dc6e1bfbac5fc3f859177f82cffbbef2e1b6f0740b9730e7f52ca2721cd44

See more details on using hashes here.

Supported by

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