getter, setter and final for Custom Classes

full support for "var a(get, set):Int".
Also, it takes into account final vars

Soon for inline custom classes

[UNTESTED]
This commit is contained in:
Jaime Humberto Macias Bustamante
2025-05-12 11:27:43 -07:00
parent 64ee722124
commit 19b5b2b049
5 changed files with 36 additions and 22 deletions
+2 -1
View File
@@ -54,7 +54,7 @@ enum Expr {
EIgnore(skip:Bool);
EConst( c : Const );
EIdent( v : String );
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool );
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool, ?isPrivate : Bool, ?isFinal : Bool, ?isInline : Bool, ?get : String, ?set : String );
EParent( e : Expr );
EBlock( e : Array<Expr> );
EField( e : Expr, f : String , ?safe : Bool );
@@ -220,6 +220,7 @@ typedef VarDecl = {
var set : Null<String>;
var expr : Null<Expr>;
var type : Null<CType>;
var isFinal : Null<Bool>;
}
typedef TypeParamDecl = {};
+6 -5
View File
@@ -889,16 +889,17 @@ class Interp {
};
customClassFields.push(fd);
case EVar(n, t, e, isPublic, isStatic, isPrivate, isFinal, isInline):
case EVar(n, t, e, isPublic, isStatic, isPrivate, isFinal, isInline, getter, setter):
var varAcc:Array<FieldAccess> = [];
if (isPublic) varAcc.push(APublic);
if (isStatic) varAcc.push(AStatic);
var vrd:VarDecl = {
get: null,
set: null,
get: getter,
set: setter,
expr: e,
type: t
type: t,
isFinal: isFinal
};
var fd:FieldDecl = {
name: n,
@@ -928,7 +929,7 @@ class Interp {
var customClassDecl:CustomClassDecl = {
classDecl: classDecl,
imports: localImports,
imports: localImports, // TODO: better way to reuse imported classes
usings: [for(u in this.usings) u.name],
pkg: null,
ogInterp: this,
+3 -2
View File
@@ -2,13 +2,14 @@ package hscript;
class InterpConfig {
// Automatic import redirect for certain classes
public static var IMPORT_REDIRECTS(default, never) = [
public static final IMPORT_REDIRECTS = [
"Type" => "hscript.proxy.ProxyType"
];
// Incase an import fails
// These are the module names
@:unreflective public static var DISALLOW_IMPORT(default, never) = [
@:unreflective
public static final DISALLOW_IMPORT = [
"Type"
];
}
+5 -2
View File
@@ -854,6 +854,8 @@ class Parser {
}
}
var ident = getIdent();
var get = null, set = null;
// TODO: getter and setter
var tk = token();
var t = null;
nextType = null;
@@ -1775,10 +1777,10 @@ class Parser {
ret : inf.ret,
}),
};
case "var":
case "var" | "final":
var name = getIdent();
var get = null, set = null;
if( maybe(TPOpen) ) {
if(id != "final" && maybe(TPOpen) ) {
get = getIdent();
ensure(TComma);
set = getIdent();
@@ -1806,6 +1808,7 @@ class Parser {
set : set,
type : type,
expr : expr,
isFinal: id == "final"
}),
};
default:
+20 -12
View File
@@ -315,15 +315,19 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
}
if (hasVar(name)) {
var v = getVar(name);
var getter = v.get != null ? v.get : 'default';
var value:Dynamic = null;
if (__allowSetGet && hasFunction('get_${name}'))
if(getter == "never")
throw 'field $name cannot be accessed for reading';
if (__allowSetGet && getter == "get" && hasFunction('get_${name}'))
value = __callGetter(name);
else if (this.interp.variables.exists(name))
value = this.interp.variables.get(name);
else {
var v = getVar(name);
if (v.expr != null) {
value = this.interp.expr(v.expr);
this.interp.variables.set(name, value);
@@ -344,10 +348,9 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
if (this.superClass is CustomClass) {
var superCustomClass:CustomClass = cast(this.superClass, CustomClass);
try {
superCustomClass.__allowSetGet = this.__allowSetGet;
return superCustomClass.hget(name);
} catch (e) {}
superCustomClass.__allowSetGet = this.__allowSetGet;
return superCustomClass.hget(name);
}
// Real Class
var fields = Type.getInstanceFields(Type.getClass(this.superClass));
@@ -366,17 +369,22 @@ class CustomClass implements IHScriptCustomAccessBehaviour {
switch (name) {
default:
if (hasVar(name)) {
if (__allowSetGet && hasFunction('set_${name}'))
var v = getVar(name);
var setter = v.set != null ? v.set : 'default';
if (setter == "never" || (v.isFinal != null && v.isFinal))
throw 'field $name cannot be accessed for writing';
if (__allowSetGet && setter == "set" && hasFunction('set_${name}'))
return __callSetter(name, val);
this.interp.variables.set(name, val);
} else if (this.superClass != null) {
if (this.superClass is CustomClass) {
var superCustomClass:CustomClass = cast(this.superClass, CustomClass);
try {
superCustomClass.__allowSetGet = this.__allowSetGet;
return superCustomClass.hset(name, val);
} catch (e:Dynamic) {}
superCustomClass.__allowSetGet = this.__allowSetGet;
return superCustomClass.hset(name, val);
}
// Real Class
if (Type.getClass(this.superClass) == null) {