Skip to content

Loading scripts

ashley edited this page Aug 7, 2026 · 5 revisions

Warning

The source code for the following classes is still undocumented. I intend on resolving this soon!

Loading script files

This refers to the standard Hscript syntax scripts, and is pretty straightforward.

This is a tiny wrapper for the Hscript interpreter and parser, and allows you to easily execute script code from a string!
The following example will execute script code from a file...

var path:String = 'test/scripts/TestScript.hxs';
var script:Script = new Script(File.getContent(path), path); // a Script is parsed immediately on creation...

script.start(); // and this starts up the script program!

Scripts have the methods onParsingError and onProgramError that are called when the script fails to parse and to initialize, respectively. These methods only log to the console by default, but are dynamic and can be overridden for custom behavior.

To call a method defined in a Script, use [Script].call('functionName', [argument1, argument2, ...]); and to get it's variables, you can use the [Script].variables map.

Loading a source-like structure

This refers to scripted modules!
Unlike script files, the implementation to run through the folder structure mostly depends on the user (you, perhaps), however you are equipped with a few classes to handle the heavier work of parsing and initializing this structure.

This is the environment all of our Creatures will inhabit, and is the base of our module structure.
This "container" basically allows all modules and scripts to know each other and be used within it!

var env:Environment = new Environment([module1, module2, ...]);

The first (and only) argument of an Environment expects an array of Modules, so you can create your Modules before the Environment - although that is the recommended (and more performant) way of creating an Environment, this argument can be omitted and [Environment].addModule(module) can be used to manually add modules instead.

This class is similar to a Script, but is used to load module code instead.
The following example will parse module code from a file...

var path:String = 'test/source/TestModule.hxs';
var module:Module = new Module(File.getContent(path), 'TestModule', ['package', 'subpackage'], path);

The second argument is the name of the module, and the third argument is an array with the packages this Module should be inside (think of splitting the package string at the top by the periods). This is used to assert the package and the module will fail to parse if it doesn't match.

A subModules array, which is composed of other Modules, can be set to import this module's base type into the other modules, and to use import modules, similarly to Haxe.

Like Script, this class has the methods onParsingError and onProgramError, with the addition of onTypeError, that is called when a type within this Module fails to initialize.

Extends Module. This will only parse import and using declarations.

var path:String = 'test/source/import.hxs';
var importModule:ImportModule = new ImportModule(File.getContent(path), path);

When in a Module's sub-modules array, all of these declarations will be imported on the Module.

Finishing up

Once all modules are added to an environment, simply call [Environment].start() to finish initializing all types!

If you want to make all of your types importable in your Scripts, include the respective Environment in the third argument of their constructors!

Example

At last, the following (relatively...) small example will load scripts located in "test/scripts", and modules located in "test/source", with the ".hxs" format (to distinguish from ".hx")!

import sys.io.File;
import sys.FileSystem;

import insanity.Environment;
import insanity.ImportModule;
import insanity.Module;
import insanity.Script;

using StringTools;


public var environment:Environment;
public var scripts:Array<Script> = [];


final scriptsPath:String = 'test/scripts';
final sourcePath:String = 'test/source';
final fileType:String = '.hxs';

var modules:Array<Module> = [];
if (FileSystem.exists(sourcePath) && FileSystem.isDirectory(sourcePath)) {
	function readModules(dir:String, ?subModules:Array<Module>) {
		subModules = (subModules == null ? [] : subModules.copy()); // so sub-modules dont leak into previous packages
		
		var modulesInFolder:Array<Module> = [];
		var subDirectories:Array<String> = [];
		
		for (file in FileSystem.readDirectory(dir)) {
			var path:String = '$dir/$file';
			
			if (FileSystem.isDirectory(path)) {
				subDirectories.push(path);
			} else if (file == 'import$fileType') {
				var module:ImportModule = new ImportModule(File.getContent(path), path);
				subModules.push(module);
			} else if (file.endsWith(fileType)) {
				var pack:Array<String> = dir.replace('$sourcePath/', '').replace(sourcePath, '').split('/');
				if (pack[0].length == 0) pack.shift();
				
				var module:Module = new Module(File.getContent(path), file.replace(fileType, ''), pack, path);
				module.subModules = subModules;
				modulesInFolder.push(module);
				subModules.push(module);
				modules.push(module);
			}
		}
		
		// this is done last to ensure all types from the current package can be imported into the sub-packages
		for (sub in subDirectories)
			readModules(sub, subModules);
	}
	readModules(sourcePath);
}

environment = new Environment(modules);
environment.start();

if (FileSystem.exists(scriptsPath) && FileSystem.isDirectory(scriptsPath)) {
	for (file in FileSystem.readDirectory(scriptsPath)) {
		if (!file.endsWith(fileType)) continue;
		
		scripts.push(new Script(File.getContent('$scriptsPath/$file'), '$scriptsPath/$file', environment));
		
		if (script.interp != null) script.start();
	}
}

Clone this wiki locally