Better access context (IN PROGRESS)

Also, throws an error if a variable with "(get, set)" doesn't have a type or a default value.
This commit is contained in:
Jaime Humberto Macias Bustamante
2025-05-15 01:07:29 -07:00
parent 1cc678fbef
commit 932e643dc9
5 changed files with 66 additions and 14 deletions
+5
View File
@@ -237,3 +237,8 @@ enum abstract FieldPropertyAccess(UInt8) {
var AGet;
var ASet;
}
enum AccessContext {
CInner(cl:String);
COuter;
}
+5 -2
View File
@@ -168,7 +168,7 @@ class Interp {
var curExpr:Expr;
#end
var _proxy(default, null):Null<CustomClass> = null;
var _proxy(default, null):Null<CustomClass> = null; // Like "scriptObject" but for Custom Classes
var _nextCallObject(default, null):Dynamic = null;
var _inCustomClass(get, never):Bool;
@@ -743,7 +743,6 @@ class Interp {
return r;
}
if (_proxy.hasVar(id)) {
var r = _proxy.hget(id);
return r;
@@ -1625,6 +1624,8 @@ class Interp {
var clsName:String = cast(o, CustomClass).className;
error(ECustom('The field ${clsName}.${f} should be accessed in a static way.'));
}
cast(o, CustomClass).accessContext = _inCustomClass ? CInner(_proxy.className) : COuter;
}
var cls = Type.getClass(o);
@@ -1679,6 +1680,8 @@ class Interp {
var clsName:String = cast(o, CustomClass).className;
error(ECustom('The field ${clsName}.${f} should be accessed in a static way.'));
}
cast(o, CustomClass).accessContext = _inCustomClass ? CInner(_proxy.className) : COuter;
}
if (useRedirects && {
+15 -5
View File
@@ -856,9 +856,9 @@ class Parser {
}
var ident = getIdent();
var get = ADefault, set = ADefault;
var hasGetSet:Bool = false;
var tk = token();
// TODO: throw "Missing ;" if tried to use (get, set) on final
// and "Property requires type-hint or initialization" on missing type.
if( tk == TPOpen && id != "final" ) {
var getId = getIdent();
switch (getId) {
@@ -879,6 +879,8 @@ class Parser {
}
ensure(TPClose);
hasGetSet = true;
tk = token();
}
@@ -895,6 +897,10 @@ class Parser {
e = parseExpr();
else
push(tk);
if(hasGetSet && (e == null || (allowTypes && t == null)))
error(ECustom("Property requires type-hint or initialization"), p1, tokenMax);
nextType = null;
mk(EVar(ident, t, e, nextIsPublic, nextIsStatic, nextIsPrivate, id == "final", nextIsInline), p1, (e == null) ? tokenMax : pmax(e));
case "while":
@@ -1119,10 +1125,10 @@ class Parser {
mk(EIgnore(true));
case CTPath(path, params):
if (params != null && params.length > 1)
error(ECustom("Typedefs can't have parameters"), tokenMin, tokenMax);
error(ECustom("Typedefs can't have parameters"), p1, tokenMax);
if (path.length == 0)
error(ECustom("Typedefs can't be empty"), tokenMin, tokenMax);
error(ECustom("Typedefs can't be empty"), p1, tokenMax);
var className = path.join(".");
var cl = Tools.getClass(className);
@@ -1137,7 +1143,7 @@ class Parser {
// todo? add import to the beginning of the file?
mk(EVar(name, null, expr));
default:
error(ECustom("Typedef, unknown type " + t), tokenMin, tokenMax);
error(ECustom("Typedef, unknown type " + t), p1, tokenMax);
null;
}
case "using":
@@ -1805,8 +1811,8 @@ class Parser {
case "var" | "final":
var name = getIdent();
var get = ADefault, set = ADefault;
var hasGetSet:Bool = false;
// TODO: throw "Missing ;" if tried to use (get, set) on final
// and "Property requires type-hint or initialization" on missing type.
if(maybe(TPOpen) && id != "final") {
var getId = getIdent();
switch(getId) {
@@ -1826,10 +1832,14 @@ class Parser {
default: unexpected(TId(getId));
}
ensure(TPClose);
hasGetSet = true;
}
var type = maybe(TDoubleDot) ? parseType() : null;
var expr = maybe(TOp("=")) ? parseExpr() : null;
if(hasGetSet && (expr == null || type == null))
error(ECustom("Property requires type-hint or initialization"), p1, tokenMax);
if( expr != null ) {
if( isBlock(expr) )
maybe(TSemicolon);
+20 -2
View File
@@ -44,6 +44,7 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
private var __cachedFunctionDecls:Map<String, FunctionDecl> = [];
private var __cachedVarDecls:Map<String, VarDecl> = [];
public var accessContext:AccessContext = COuter;
public var __allowSetGet:Bool = false;
public var __allowPrivateAccess:Bool = false;
@@ -344,10 +345,14 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
if (hasVar(name)) {
var v = getVar(name);
var getter = v.get;
var isInner = switch (accessContext) {
case CInner(cl): return cl == this.className;
default: false;
}
var value:Dynamic = null;
if(getter == ANever || getter == ANull && !__allowPrivateAccess)
if(getter == ANever || getter == ANull && (!isInner || !__allowPrivateAccess))
throw 'field $name cannot be accessed for reading';
if (__allowSetGet && getter == AGet) {
@@ -370,6 +375,7 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
if (this.superClass != null) {
if (superHasField(name)) {
// Anonymous structure as a super class???
if (Type.getClass(this.superClass) == null) {
// Anonymous structure
if (Reflect.hasField(this.superClass, name))
@@ -383,6 +389,10 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
superCustomClass.__allowSetGet = this.__allowSetGet;
superCustomClass.__allowPrivateAccess = this.__allowPrivateAccess;
superCustomClass.accessContext = switch (accessContext) {
case CInner(_): CInner(superCustomClass.className);
default: COuter;
}
return superCustomClass.hget(name);
}
@@ -407,8 +417,12 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
if (hasVar(name)) {
var v = getVar(name);
var setter = v.set;
var isInner = switch (accessContext) {
case CInner(cl): return cl == this.className;
default: false;
}
if (setter == ANever || setter == ANull && !__allowPrivateAccess || (v.isFinal && !initializing))
if (setter == ANever || setter == ANull && (!isInner || !__allowPrivateAccess) || (v.isFinal && !initializing))
throw 'field $name cannot be accessed for writing';
if (__allowSetGet && setter == ASet) {
@@ -437,6 +451,10 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
superCustomClass.__allowSetGet = this.__allowSetGet;
superCustomClass.__allowPrivateAccess = this.__allowPrivateAccess;
superCustomClass.accessContext = switch (accessContext) {
case CInner(_): CInner(superCustomClass.className);
default: COuter;
}
return superCustomClass.hset(name, val);
}
// Real Class
+21 -5
View File
@@ -1,5 +1,6 @@
package hscript.customclass;
import hscript.Expr.AccessContext;
import hscript.proxy.ProxyType;
import hscript.customclass.utils.FunctionUtils;
import haxe.Constraints.Function;
@@ -33,6 +34,10 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour {
public var __allowPrivateAccess:Bool = false;
public var accessContext:AccessContext = COuter;
public final name:String;
public function new(classDecl:Expr.ClassDecl, imports:Map<String, CustomClassImport>, usings:Array<String>, ?pkg:Array<String>, ?ogInterp:Interp, ?isInline:Bool) {
this.classDecl = classDecl;
this.imports = imports;
@@ -41,6 +46,11 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour {
this.ogInterp = ogInterp;
this.isInline = isInline;
// Cache the classname
var pkg = pkg != null ? '${pkg.join(".")}.' : "";
var className = classDecl.name;
this.name = '$pkg$className';
if(ogInterp != null) {
staticInterp.importFailedCallback = ogInterp.importFailedCallback;
staticInterp.errorHandler = ogInterp.errorHandler;
@@ -189,10 +199,14 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour {
if(hasVar(name)) {
var v = getVar(name);
var getter = v.get;
var isInner = switch (accessContext) {
case CInner(cl): return cl == this.toString();
default: false;
}
var r:Dynamic = null;
if (getter == ANever || getter == ANull && !__allowPrivateAccess)
if (getter == ANever || getter == ANull && (!isInner || !__allowPrivateAccess))
throw 'field $name cannot be accessed for reading';
if(__allowSetGet && getter == AGet){
@@ -226,8 +240,12 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour {
if (hasVar(name)) {
var v = getVar(name);
var setter = v.set;
var isInner = switch (accessContext) {
case CInner(cl): return cl == this.toString();
default: false;
}
if (setter == ANever || setter == ANull && !__allowPrivateAccess || v.isFinal)
if (setter == ANever || setter == ANull && (!isInner || !__allowPrivateAccess) || v.isFinal)
throw 'field $name cannot be accessed for writing';
if (__allowSetGet && setter == ASet) {
@@ -260,9 +278,7 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour {
}
public function toString():String {
var pkg = pkg != null ? '${pkg.join(".")}.' : "";
var name = classDecl.name;
return '$pkg$name';
return name;
}
}