Sidebar

Home



Expressions V4


Tutorials

How-To

Reference

  Lexical basics
  Type system
  Variables and assignment
  Operators
  Expression rules
  Control flow
  Functions
  Built-in functions
   None and NaN
   Arithmetic
   Algebra
   Logarithmic and Exponential
   Trigonometric
   Rounding and Centering
   Strings
   Output, Formatting, Clipboard, and Errors
   Dialog Functions
   Platform and Paths
  Methods and properties
  Built-in methods
   Common Value Methods
   Number Methods
   String Basic Methods
   String Slice Methods
   String Parsing Methods
   String Formatting Methods
   String Regex Methods
   String Trim and Case Methods
  Objects
  Built-in objects
   Global objects
    settings
    controller
    session
    python
   Collections
    array
    map
    bytes
   File Format I/O
    image_data
    image_stream
   Utils
    crypto
    timer
   Comm
    serial
   Dialogs
    file_open
    file_save
    msg_ok
    msg_ok_cancel
    msg_yes_no
    msg_password
   GUI objects
    window
    panel
    group
    splitpanel
    label
    textbutton
    drawablebutton
    togglebutton
    togglegroup
    textinput
    textedit
    numinput
    slider
    combobox
    listbox
    progressbar
    led
    separator
    menu
    image
    snake
  Classes and user-defined objects
  Include system
  Error model
  Execution model and sessions
  Host integration
  Limits and performance
  Formal reference
  Glossary

Cookbook

exprv4:reference:include_system

Include System

The include system imports Expr code from another file at parse time.

Use includes for reusable functions, classes, constants, and shared script libraries.


Basic Include

Syntax:

include 'MyMath.expr'

The included file is parsed and inserted into the current program.

Example library file:

// MyMath.expr
function Add(a, b)
{
    return a + b;
}
 
function Sub(a, b)
{
    return a - b;
}

Using it:

include 'MyMath.expr'
 
print(Add(2, 3));
print(Sub(8, 5));

An include statement can be followed by a semicolon, but it does not require one:

include 'MyMath.expr';
include 'Other.expr'

Where Include Is Allowed

`include` is a top-level statement.

It is valid at the top level of a script:

include 'Library.expr'
 
result = LibraryValue();

It is not valid inside blocks, functions, or classes:

if (1)
{
    include 'Library.expr'     // error
}

An include statement must start a statement. It cannot be used as part of an expression.


Included Content

Included code is parsed as if it appeared in the including script.

This means an included file can contain:

  • function declarations
  • class declarations
  • normal top-level statements
  • other include statements

For library files, prefer function and class declarations only. Top-level statements in included files run each time the file is included.


Namespaced Include

Use `as` to import a file under a namespace alias.

include 'MyMath.expr' as MathLib
 
print(MathLib::Add(2, 3));

With a namespaced include, top-level function and class declarations from the included file are placed into the alias namespace.

// MyMath.expr
function Add(a, b)
{
    return a + b;
}
include 'MyMath.expr' as MathLib
 
MathLib::Add(2, 3);      // OK
Add(2, 3);               // error unless another Add exists

The alias after `as` is a namespace name, such as `MathLib`.


Namespaced Classes

Namespaced includes also apply to class declarations.

// Tools.expr
class ToolInfo(number, diameter)
{
    Number = number;
    Diameter = diameter;
 
    function Radius()
    {
        return Diameter / 2;
    }
}
include 'Tools.expr' as Tools
 
tool = Tools::ToolInfo(3, 6.0);
print(tool.Radius());

If an included class or function already has a namespace, the include alias is the namespace used for the imported definition.


Top-level Statements With Namespace Alias

The namespace alias applies to imported top-level function and class declarations.

It does not rewrite arbitrary top-level statements.

For example, this file is not a good candidate for aliased include:

// Init.expr
value = Add(2, 3);

If it is included with an alias, the call expression is not rewritten to `Alias::Add(…)`.

Keep aliased include files definition-only unless you are deliberately executing top-level code.


Duplicate Includes

Includes are not treated as `pragma once`.

Including the same file more than once is allowed.

Effects of duplicate include:

  • Function definitions with the same fully-qualified name are replaced by the later definition.
  • Class definitions with the same fully-qualified name are replaced by the later definition.
  • Top-level statements in the included file are inserted again and can run again.
  • Including the same file with different aliases creates separate namespaced definitions.

Example:

include 'MyMath.expr' as A
include 'MyMath.expr' as B
 
A::Add(1, 2);
B::Add(1, 2);

Recursive Includes

Expr detects active recursive include chains.

If a file includes itself directly or indirectly while it is already being parsed, parsing fails with a recursive include error.

Example:

// A.expr
include 'B.expr'
 
// B.expr
include 'A.expr'     // recursive include error

Expr also limits include nesting depth. Include nesting deeper than 16 levels is rejected.


Path Resolution

Include file names are strings.

include './lib/MyMath.expr'
include 'LocalHelper.expr'
include 'C:/PlanetCNC/scripts/MyMath.expr'

Path resolution is handled by the host path resolver.

General rules:

  • Absolute paths can be used when the host allows them.
  • `./File.expr` is resolved from the profile path.
  • `../File.expr` is also profile-relative, then moves to the parent of the profile folder.
  • `File.expr` is resolved from the source path.
  • `~/File.expr` is also resolved from the source path.
  • `path(…)`, `include`, and file-loading objects use the same host path rules.

Use profile-relative include paths for shared profile libraries:

include './lib/probing/probe_job.expr' as Probe
include './lib/atc/tool_change.expr' as ATC

Use source-relative include paths for helper files beside the current source script:

include 'probe_steps.expr' as Steps
include '~/local_report.expr' as Report

Do not use `../lib/…` when you mean a library inside the profile folder. Because it starts with `.`, it resolves from the profile path and goes outside the profile folder.

See How relative paths work.


Runtime Path Context

Runtime path resolution uses the current source path and profile path from the host evaluation context.

A function or class method should use explicit profile-relative paths for shared profile assets:

function LoadLogo()
{
    return image_data().load('./assets/images/logo.png');
}

Use paths without a leading dot for files that belong beside the current source script:

function LoadJobData()
{
    return bytes().load('job_data.csv');
}

Parsing Options

Included files are parsed with strict default Expr parsing options.

They do not inherit caller compatibility options enabled by a host context, such as:

  • G-code hash variable compatibility
  • named operator compatibility
  • modifiable comments compatibility

Write include files using normal Expr syntax.


For reusable libraries:

  • Put shared functions and classes in include files.
  • Avoid top-level side effects in library include files.
  • Use `as Namespace` for shared libraries to avoid name collisions.
  • Use `./lib/…` for shared profile libraries, and no leading dot for files beside the current source script.
  • Avoid circular include relationships.

Example:

include './lib/Geometry.expr' as Geometry
 
area = Geometry::CircleArea(10);

Previous: Classes and user-defined objects

Next: Error model

exprv4/reference/include_system.txt · Last modified: by 127.0.0.1

Page Tools