diff --git a/hscript/Expr.hx b/hscript/Expr.hx index 0cfc5ef..a8d5317 100644 --- a/hscript/Expr.hx +++ b/hscript/Expr.hx @@ -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 ); EField( e : Expr, f : String , ?safe : Bool ); @@ -220,6 +220,7 @@ typedef VarDecl = { var set : Null; var expr : Null; var type : Null; + var isFinal : Null; } typedef TypeParamDecl = {}; diff --git a/hscript/Interp.hx b/hscript/Interp.hx index bd02c63..ee2d4f9 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -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 = []; 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, diff --git a/hscript/InterpConfig.hx b/hscript/InterpConfig.hx index aa6afb6..28fe7ba 100644 --- a/hscript/InterpConfig.hx +++ b/hscript/InterpConfig.hx @@ -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" ]; } \ No newline at end of file diff --git a/hscript/Parser.hx b/hscript/Parser.hx index f5ed22d..3fc1d6a 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -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: diff --git a/hscript/customclass/CustomClass.hx b/hscript/customclass/CustomClass.hx index c154c3b..d1af6b3 100644 --- a/hscript/customclass/CustomClass.hx +++ b/hscript/customclass/CustomClass.hx @@ -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) {