diff --git a/CHANGELOG.md b/CHANGELOG.md index ea09b8a..8826620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Reworked shared variables. (see [#36](https://github.com/Kriptel/RuleScript/pull/36)) - Wildcard import. - ScriptedModule. - Shared variables between interps. (see [#29](https://github.com/Kriptel/RuleScript/pull/29)) diff --git a/docs/context.md b/docs/context.md index 7d77995..f689622 100644 --- a/docs/context.md +++ b/docs/context.md @@ -22,9 +22,7 @@ - `types` - Stores all previously `defined` types. -- `publicVariables` - **Public** variables, each entry in this array is added using the meta `@:contextValue('public')`, or the keyword `public`. - -- `staticVariables` - **Static** variables, each entry in this array is added using the meta `@:contextValue('static')`, or the keyword `static`. +- `variables` - **Public** & **Static** variables, each entry in this array is added using the meta `@:contextValue('public')`, or the keyword `public`. --- diff --git a/rulescript/Context.hx b/rulescript/Context.hx index f76d710..7a6320b 100644 --- a/rulescript/Context.hx +++ b/rulescript/Context.hx @@ -1,8 +1,10 @@ package rulescript; -import rulescript.scriptedClass.RuleScriptedClass.ScriptedClass; import rulescript.types.ScriptedAbstract; import rulescript.types.ScriptedType; +import rulescript.scriptedClass.RuleScriptedClass.ScriptedClass; +import rulescript.types.context.EVariableModifiers; +import rulescript.types.context.EVariableDeclarations; /** * The Context stores types to preserve repeated imports, @@ -10,39 +12,33 @@ import rulescript.types.ScriptedType; * * All script types automatically inherit the Context. */ -class Context -{ +class Context { public var types:Map = []; + public var variables:Map = []; - public var publicVariables:Map = []; - public var staticVariables:Map = []; + @:deprecated public var publicVariables(default, never):Map = []; + @:deprecated public var staticVariables(default, never):Map = []; public function new() {} - public function reset():Void - { + public function reset():Void { types = []; resetVariables(); } - public function resetVariables():Void - { - publicVariables = []; // yuhuh -orbl - staticVariables = []; + public function resetVariables():Void { + variables = []; // yuhuh -orbl } - public function resolveType(path:String):Dynamic - { + public function resolveType(path:String):Dynamic { if (types.exists(path)) return types[path]; - else - { + else { final t:Dynamic = Tools.resolveType(path, this); if (t is ScriptedType) - switch (cast(t, ScriptedType).__rulescript_type) - { + switch (cast(t, ScriptedType).__rulescript_type) { case CLASS: @:privateAccess cast(t, ScriptedClass).interp.access.context = this; case ABSTRACT: @@ -54,3 +50,5 @@ class Context }; } } + +typedef ContextVariable = {modifier:EVariableModifiers, declaration:EVariableDeclarations, value:Dynamic, ?parent:String}; diff --git a/rulescript/interps/RuleScriptInterp.hx b/rulescript/interps/RuleScriptInterp.hx index fc340dd..44f9dae 100644 --- a/rulescript/interps/RuleScriptInterp.hx +++ b/rulescript/interps/RuleScriptInterp.hx @@ -11,6 +11,8 @@ import rulescript.types.ScriptedEnum; import rulescript.types.ScriptedType; import rulescript.types.ScriptedTypeUtil; import rulescript.types.ScriptedTypedef; +import rulescript.types.context.EVariableModifiers; +import rulescript.types.context.EVariableDeclarations; using rulescript.Tools; @@ -96,13 +98,8 @@ class RuleScriptInterp extends hscript.Interp implements IInterp v = get(superInstance, id); // SHARED VARIABLES - if (v == null && context != null) - { - if (context.staticVariables.exists(id)) - v = context.staticVariables.get(id); - if (context.publicVariables.exists(id)) - v = context.publicVariables.get(id); - } + if (v == null && context != null && context.variables.exists(id)) + v = context.variables.get(id).value; if (v == null) error(EUnknownVariable(id)); // fixes - orbl @@ -151,10 +148,12 @@ class RuleScriptInterp extends hscript.Interp implements IInterp { if (superInstance != null && (superFields.contains(name) || superFields.contains('set_' + name))) Reflect.setProperty(superInstance, name, v); - else if (context != null && context.staticVariables.exists(name)) - context.staticVariables.set(name, v); - else if (context != null && context.publicVariables.exists(name)) - context.publicVariables.set(name, v); + else if (context != null && context.variables.exists(name)) { + final cv:rulescript.Context.ContextVariable = context.variables.get(name); + if (cv.declaration == FINAL && cv.parent != scriptName) + error(ECustom('$name: Unable to override final variable defined by another script.')); + else context.variables.set(name, {modifier: cv.modifier, declaration:cv.declaration, value: v, parent: scriptName}); + } else { var lastValue = variables.get(name); @@ -242,7 +241,7 @@ class RuleScriptInterp extends hscript.Interp implements IInterp if ((!locals.exists(id) && !variables.exists(id)) && (!superFields.contains(id) && !superFields.contains('get_$id')) - && (context == null || !context.staticVariables.exists(id) && !context.publicVariables.exists(id))) + && (context == null || !context.variables.exists(id))) { final typePath:String = path.join('.'); @@ -278,14 +277,14 @@ class RuleScriptInterp extends hscript.Interp implements IInterp return switch (n) { case ':contextValue' if (context != null): - var isFunction:Bool = false; - + var isFunction:Bool = false, isFinal:Bool = false; final n:Null = switch (Tools.getExpr(e)) { case EFunction(_, _, n): isFunction = true; n; - case EProp(n, _), EVar(n, _): n; + case EProp(n, _): n; + case EVar(n, _,_,_,f): isFinal = f; n; default: null; }; @@ -293,13 +292,22 @@ class RuleScriptInterp extends hscript.Interp implements IInterp if (isFunction && depth == 0) { - return (isStatic ? context.staticVariables : context.publicVariables)[n] = this.expr(e); + return context.variables[n] = { + value: this.expr(e), + declaration: isFinal ? EVariableDeclarations.FINAL : EVariableDeclarations.VAR, + modifier: isStatic ? EVariableModifiers.STATIC : EVariableModifiers.PUBLIC, + parent: scriptName + }; } else if (depth == 0) { this.expr(e); - - (isStatic ? context.staticVariables : context.publicVariables).set(n, resolve(n)); + context.variables.set(n, { + value: resolve(n), + declaration: isFinal ? EVariableDeclarations.FINAL : EVariableDeclarations.VAR, + modifier: isStatic ? EVariableModifiers.STATIC : EVariableModifiers.PUBLIC, + parent: scriptName + }); } else { @@ -314,7 +322,7 @@ class RuleScriptInterp extends hscript.Interp implements IInterp case EVar(n, _, e, global, _): if (global) { - if (context == null || (!context.staticVariables.exists(n) && !context.publicVariables.exists(n))) + if (context == null || !context.variables.exists(n)) variables.set(n, (e == null) ? null : this.expr(e)); } else diff --git a/rulescript/types/context/EVariableDeclarations.hx b/rulescript/types/context/EVariableDeclarations.hx new file mode 100644 index 0000000..b013e90 --- /dev/null +++ b/rulescript/types/context/EVariableDeclarations.hx @@ -0,0 +1,6 @@ +package rulescript.types.context; + +enum abstract EVariableDeclarations(Int) { + var FINAL:EVariableDeclarations = 0; + var VAR:EVariableDeclarations = 1; +} \ No newline at end of file diff --git a/rulescript/types/context/EVariableModifiers.hx b/rulescript/types/context/EVariableModifiers.hx new file mode 100644 index 0000000..86508d2 --- /dev/null +++ b/rulescript/types/context/EVariableModifiers.hx @@ -0,0 +1,6 @@ +package rulescript.types.context; + +enum abstract EVariableModifiers(Int) { + var PUBLIC:EVariableModifiers = 0; + var STATIC:EVariableModifiers = 1; +} \ No newline at end of file