Skip to content

Commit

Permalink
0.0.2 - Abstracts in scripts
Browse files Browse the repository at this point in the history
0.0.2 :

Added :
- Abstract statics support
- Date and Datetools defaults for RuleScriptInterp

Fixed :
- Fixed bug when code ignored properties
  • Loading branch information
Kriptel committed Sep 7, 2024
1 parent 37e7522 commit 9951584
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/.vscode
/test/export
hxformat.json
/test/dump
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Changelog

# 0.0.2 :

### Added :
- Abstract statics support
- Date and Datetools defaults for RuleScriptInterp

### Fixed :
- Fixed bug when code ignored properties

# 0.0.1 :

### Initial Release
69 changes: 48 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ Hscript addon with imports, usings, string interpolation and more.

## Features:

### Package :
### Package
package keyword (optional).
```haxe
package scripts.hello.world;
```
### Import :
### Import
```haxe
import haxe.ds.StringMap;
var map = new StringMap();
map.set("Hello","World");
trace(map.get("Hello")); // World
```
### Import with alias:
### Import with alias
you can use `as` or `in` keywords alias.
```haxe
import haxe.ds.StringMap as StrMap;
Expand All @@ -34,7 +34,7 @@ map.set("Hello","World");
trace(map.get("Hello")); // World
```

### Using:
### Using
```haxe
using Reflect;
Expand All @@ -43,12 +43,12 @@ var a = {
};
trace(a.getProperty("Hello")); // World
```

### String interpolation (Experimental)
RuleScript supports [String Interpolation](https://haxe.org/manual/lf-string-interpolation.html), but you can only use identifiers, double quotes string, calls without arguments and `+` operator.
```haxe
var a = 'Hello';
return 'RuleScript: $a World'; // RuleScript: Hello World
trace('RuleScript: $a World'); // RuleScript: Hello World
```
```haxe
var a = {
Expand All @@ -57,33 +57,60 @@ var a = {
c:'World'
};
return '${a.a}: ${a.b() + " " + a.c}'; // RuleScript: Hello World
trace('${a.a}: ${a.b() + " " + a.c}'); // RuleScript: Hello World
```

### Abstracts in script

RuleScriptAbstracts.txt in any classpath :
```
test.HelloWorldAbstract
```

test/HelloWorldAbstract.hx :
```haxe
@:keep
abstract HelloWorldAbstract(String) from String to String
{
public static function rulescriptPrint():HelloWorldAbstract
return 'Hello World';
}
```
Script :
```haxe
import test.HelloWorldAbstract;
trace(HelloWorldAbstract.rulescriptPrint()); // 'Hello World'
```
More templates in `test/src/Main.hx`.

# Limitations

- [String interpolations](https://haxe.org/manual/lf-string-interpolation.html) don't support many functions
- Script `using` callback supports max number of arguments is 8.
- [Wildcard imports](https://haxe.org/manual/type-system-import.html#wildcard-import) don't support.
- AbstractMacro ports only static fields

# To Do:
# To Do
- Lua Parser
- Importing abstract classes in scripts
- Improve String Interpolation
- Improve hscript module parser

# Install

1. Installing lib :
- Haxelib : `haxelib git rulescript https://github.com/Kriptel/RuleScript.git`
- Hmm : `hmm git rulescript https://github.com/Kriptel/RuleScript.git`
2. Adding lib to your project :
- Hxml :
```hxml
-lib rulescript
```
- Lime/OpenFL :
```xml
<haxelib name="rulescript"/>
```
1. Installing lib:

Haxelib : `haxelib git rulescript https://github.com/Kriptel/RuleScript.git`

Hmm : `hmm git rulescript https://github.com/Kriptel/RuleScript.git`
2. Adding lib to your project:

Hxml :
```hxml
-lib rulescript
```
Lime/OpenFL :
```xml
<haxelib name="rulescript"/>
```
2 changes: 2 additions & 0 deletions extraParams.hxml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@
--macro addMetadata('@:build(rulescript.macro.ExprMacro.buildCheckerDefaults())', 'hscript.Checker')

--macro addMetadata('@:build(rulescript.macro.ExprMacro.buildMacroDefaults())', 'hscript.Macro')

--macro rulescript.macro.Converter.init()
4 changes: 2 additions & 2 deletions haxelib.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"url" : "https://github.com/Kriptel/RuleScript",
"license": "MIT",
"description": "Hscript addon with imports, string interpolation and more",
"version": "0.0.1",
"releasenote": "Initial Release",
"version": "0.0.2",
"releasenote": "Abstracts in script",
"dependencies": {
"hscript":""
},
Expand Down
13 changes: 13 additions & 0 deletions rulescript/Abstracts.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package rulescript;

import rulescript.macro.AbstractMacro;

using StringTools;

class Abstracts
{
public static dynamic function resolveAbstract(name:String):Class<Dynamic>
{
return Type.resolveClass('rulescript.__abstracts.${name.substring(0, name.lastIndexOf('.') + 1) + '_' + name.substring(name.lastIndexOf('.') + 1)}');
}
}
21 changes: 15 additions & 6 deletions rulescript/RuleScriptInterp.hx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class RuleScriptInterp extends hscript.Interp
variables.set('Type', Type);
variables.set('Reflect', Reflect);
variables.set('StringTools', StringTools);
variables.set('Date', Date);
variables.set('DateTools', DateTools);

#if sys
variables.set('Sys', Sys);
Expand Down Expand Up @@ -55,6 +57,9 @@ class RuleScriptInterp extends hscript.Interp
if (t == null)
t = Type.resolveClass(path);

if (t == null)
t = Abstracts.resolveAbstract(path);

if (t == null)
t = Type.resolveEnum(path);

Expand All @@ -81,19 +86,23 @@ class RuleScriptInterp extends hscript.Interp
return null;
}

/**
* hasField not works for properties
* If getProperty object is null, interp tries to get prop from usings
*/
override function get(o:Dynamic, f:String):Dynamic
{
if (Reflect.hasField(o, f))
return super.get(o, f);
var prop:Dynamic = super.get(o, f);
if (prop != null)
return prop;

for (cl in usings)
{
if (Reflect.hasField(cl, f))
return Tools.usingFunction.bind(o, Reflect.getProperty(cl, f), _, _, _, _, _, _, _, _);
var prop:Dynamic = Reflect.getProperty(cl, f);
if (prop != null)
return Tools.usingFunction.bind(o, prop, _, _, _, _, _, _, _, _);
}

error(ECustom('$o has no field $f'));

return null;
}
}
76 changes: 76 additions & 0 deletions rulescript/macro/AbstractMacro.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package rulescript.macro;

import haxe.macro.Context;
import haxe.macro.Expr;
import sys.FileSystem;
import sys.io.File;

using StringTools;

class AbstractMacro
{
/**
* Converts abstract to class
*/
#if !macro macro #end public static function buildAbstract(name:String, pack:String):Array<Field>
{
var fields = Context.getBuildFields();
var pos = Context.currentPos();

var type = Context.getLocalClass();

var isEnum:Bool = type.get().meta.has(':enum');

var cl = macro class {};

var imports = Context.getLocalImports();

imports.push({
path: name.split('.').map(s -> {
name: s,
pos: pos
}),
mode: INormal
});

if (name.contains('.'))
{
var list = name.split('.');

while (list.length > 1)
pack += '.' + list.shift();

name = list[0];
}

cl.name = '_' + name;
cl.pack = pack.split('.');

for (f in fields)
{
if (isEnum && (f.kind.match(FVar(_, _))))
{
cl.fields.push({
name: f.name,
doc: f.doc,
access: [APublic, AStatic],
kind: switch (f.kind)
{
case FVar(t, e) if (e != null):
f.kind;
default:
FVar(macro :String, macro $v{f.name});
},
pos: f.pos,
meta: f.meta
});
}
else if (f.access.contains(AStatic))
cl.fields.push(f);
}

Context.defineModule('$pack._$name', [cl], imports);

return fields;
}
}
37 changes: 37 additions & 0 deletions rulescript/macro/Converter.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package rulescript.macro;

import haxe.macro.Compiler;
import haxe.macro.Context;
import haxe.macro.Expr;
import sys.FileSystem;
import sys.io.File;

using StringTools;

class Converter
{
// Language server shows errors...
public static function init()
{
var files:Array<String> = [];

var filename:String = Context.definedValue('rulescript_abstracts_file_path') ?? 'RuleScriptAbstracts.txt';

var abstractsList:Array<String> = [];

for (dir in Context.getClassPath())
if (FileSystem.exists(dir + filename))
for (abs in parseFile(File.getContent(dir + filename)))
if (!abstractsList.contains(abs))
abstractsList.push(abs);

for (name in abstractsList)
Compiler.addMetadata('@:build(rulescript.macro.AbstractMacro.buildAbstract("$name","rulescript.__abstracts"))', name);
}

static function parseFile(content:String):Array<String>
{
var text:String = content.replace('\r', '').replace(' ', '');
return text.split('\n');
}
}
22 changes: 22 additions & 0 deletions test/src/Main.hx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Main
packageTest();
importAndUsingTest();
stringInterpolationTest();
testAbstract();
}
catch (e)
trace(e?.details());
Expand Down Expand Up @@ -135,6 +136,27 @@ class Main
");
}

public static function testAbstract()
{
runScript('
import test.HelloWorldAbstract;

return HelloWorldAbstract.rulescriptPrint();
');

runScript('
import test.HelloWorldAbstract as Hw;

return Hw.rulescriptPrint();
');

runScript("
import test.HelloWorldAbstract as Hw;
return '${Hw.RULESCRIPT}: ${Hw.hello} ${Hw.world}';
");
}

public static function runScript(code:String)
{
Sys.println('\n[Running code #${++callNum}]: "$code"\n\n [Result]: ${script.tryExecute(code)}');
Expand Down
2 changes: 2 additions & 0 deletions test/src/RuleScriptAbstracts.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TestAbstract
test.HelloWorldAbstract
12 changes: 12 additions & 0 deletions test/src/Test.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package;

class Test
{
public var test:Int = 123456;

public function new(?test:Int)
{
if (test != null)
this.test = test;
}
}
Loading

0 comments on commit 9951584

Please sign in to comment.