-
Notifications
You must be signed in to change notification settings - Fork 0
Library differences
HscriptInsanity has a really different feature set compared to the original Hscript...
This library's main goal is to implement most of the original Haxe language into scripting!
Perchance.
Since this fork introduces a lot of features (seen below), it does have the disadvantage of performing relatively slower.
Speed isn't a huge priority for me right now, but I hope to make performance improvements and optimizations after the main feature set is finished.
(If you think you can help improve this project, feel free to open issues or pull requests, too!)
-
The original Hscript library is better suited for simple prototyping and evaluating small expressions! As such, it should be a bit faster and more lightweight.
-
But if you want Haxe's high range of features on your hands, or to implement heavy modding support in your project, consider giving this library a shot!
You can use the insanity.Script class to easily execute code from a string! Look at the Loading scripts page for a quick rundown.
The ability to define new types in scripts is the largest feature available in this library!
Scripted types can be defined within both Hscript scripts and modules.
Refer to the Defining scripted types page.
You can use the insanity.Module class to execute module code from a string, and create custom modules and types! Look at the Loading scripts page to learn how to implement this, along with a scripted "source" folder similar to the real Haxe language, in your project with HscriptInsanity!
Type definitions are currently limited to what is listed in the Scripted types section above.
Abstract and enum abstract features are supported!! See the page Working wtih abstracts to see what you can or cannot do with abstracts in scripts.
import flixel.util.FlxColor;
function colorToString(color:FlxColor)
return '(red: ${color.red} | green: ${color.green} | blue: ${color.blue})';
var color:FlxColor = cast 0xff0040; // you can also use cast(0xff0040, FlxColor)
trace(colorToString(color)); // (red: 255 | green: 0 | blue: 64)
color.green = FlxColor.GREEN.green;
trace(colorToString(color)); // (red: 255 | green: 128 | blue: 64)Classes defined with the @:structInit metadata can be constructed in Hscript by passing a struct / JSON object!
Warning
Struct init classes without constructors can still be created by using new (unlike Haxe).
var pos:insanity.backend.Expr.Position = {origin: 'me', line: 0};
trace(pos); // insanity.backend.Expr.Position
trace(pos.origin); // "me"
function returnPosition():insanity.backend.Expr.Position return {origin: 'not me', line: 1};
var pos = returnPosition();
trace(pos); // insanity.backend.Expr.Position
trace(pos.origin); // "not me"The import keyword is supported!
You can import types by module or package path (wildcard), like the actual language. Importing a single type, type field, and module level field is also supported, as well as setting aliases!
All bottom level classes like Reflect, Type and your Main app class should similarly also be exposed by default in scripts.
import sys.*; // sys package wildcard
import Reflect.getProperty as get;
trace(FileSystem.exists('Main.hx'));
trace(get({hi: 123}, 'hi'));You can also import type alias typedefs, and module level fields! Due to Haxe stripping type parameters at runtime, although you can also import struct / json typedefs, their structure isn't enforced at all.
All compile-time type information can be retrieved with insanity.backend.TypeCollection.main.
The using keyword is supported!
Type checking is not enforced due to aforementioned reasons, and may or may not be implemented to some extent in the future.
using Lambda;
var array:Array<Int> = [1, 2, 3, 4, 5];
array = array.map(function(item:Int) return (item == 3 ? 10 : item));
trace(array); // [1, 2, 10, 4, 5]Enums can be imported and created in Hscript, with and without constructors.
You can also match enums in switch cases!
// in the source code ...
enum TestEnum {
Hi(message:String);
Bye;
}
// in a script ...
import TestEnum;
trace(Hi('hello!!'));
trace(Bye);Haxe's string interpolation feature is fully supported!
var test:Int = 1234;
trace('hello $test ${'can also be nested!! $$${test + 3210}'}');Haxe's advanced switch-case pattern matching features are fully supported!
var struct:Dynamic = {name: 'Haxe', rating: 'Awesome'};
trace(switch (struct) {
case {name: a, rating: b}:
'$a is $b';
default:
'no awesome language found';
}); // Haxe is AwesomeHaxe's property accessors can be defined in variables within scripts and scripted classes!
var customSetter(default, set):Dynamic = 123;
function set_customSetter(v:Dynamic):Dynamic {
trace('setting to $v !');
return customSetter = v;
}
customSetter = 456;You can now access fields from modules and types in scripts without having to import them beforehand!
trace(haxe.io.Bytes.ofString('hello world').getString(0, 5)); // helloHaxe's regular expression syntax can now be used in Hscript, alternatively to new EReg()!
trace(~/hx/i.replace('HX is Awesome', 'Haxe')); // Haxe is AwesomeProgram exceptions in Scripts and Modules now throw an InterpException, containing more detailed error info, akin to Haxe's exception call stack.
Also imposes a limit for the call stack before throwing a Stack overflow exception, to prevent the program from freezing indefinitely from recursion. This is 200 by default, but can be adjusted with callStackDepth in an Interp instance!
Exception: ouch...
Called from test/TestScript.hxs.crash (test/TestScript.hxs line 2 column 8)
Called from script test/TestScript.hxs (test/TestScript.hxs line 4 column 1)
Called from Main.main (Main.hx line 10 column 3)
-
Rest
Rest argument can now be used in functions!
-
Optional arguments
Providing a default value for an argument now treats it as optional, regardless of a
?preceding the argument name (which is, presumably, unintended behavior in the original library)A bug where default argument values didn't work as intended in specific conditions is also corrected.
function test(?arg = false, arg2 = false) { trace(arg); trace(arg2); }
Scripts now include the default compilation defines / preprocessor values by default, and you can include more custom defines.
Comparisons are now also supported in conditionals, and a small parsing bug with conditionals in the original library has also been fixed!
#if (haxe < '4.3.7')
trace('I\'m old!');
#endThe #error command is also supported (if you ever need to use this).
#error 'ouch'Warning
This only applies to the first level, thus nested maps won't be inferred if empty. (todo ?)
You can now declare empty maps, inferring from type parameters (in the original library, [] usually just declares an empty array).
var map:Map<String, Dynamic> = [];
trace(Type.typeof(map));
var array = [];
trace(Type.typeof(array));Map comprehension is now also supported, to accompany array comprehension!
var map:Map<Int, String> = [for (i in 0 ... 5) i => 'number ${i}'];-
Hashlink
- You can clone a class that makes use of
@:hlNativeviaHLMacro, to fix and make it properly usable in Hscript.- This fix is only applied in the
Mathclass by default.
- This fix is only applied in the
- An internal limitation where attempting to call methods with 9 arguments or more threw a "Too many arguments" error has now been circumvented (also via
HLMacro).- This also extended to classes with constructors with 9 arguments or more, making them impossible to instantiate; this too should be fixed!
- This fix is automatically applied to every class when targetting HashLink; if you encounter any compiling errors, please open an issue!
- You can clone a class that makes use of
HscriptInsanity by emi3