Property combination check

Also, it parses 'dynamic'.

Still working on getter/setter for variables
This commit is contained in:
Jaime Humberto Macias Bustamante
2025-05-16 14:10:20 -07:00
parent 22d6404799
commit 1bcbce2d5b
3 changed files with 70 additions and 19 deletions
+2 -1
View File
@@ -233,9 +233,10 @@ enum EnumType {
enum abstract FieldPropertyAccess(UInt8) {
var ADefault;
var ANull;
var ANever;
var AGet;
var ASet;
var ADynamic;
var ANever;
}
enum AccessContext {
+24 -4
View File
@@ -65,9 +65,10 @@ enum abstract ScriptObjectType(UInt8) {
class DeclaredVar {
public var r:Dynamic;
public var depth:Int;
public var isFinal:Null<Bool> = null;
// TODO: getter/setter for variables
public var getter:FieldPropertyAccess = null;
public var setter:FieldPropertyAccess = null;
public var getter:Null<FieldPropertyAccess> = null;
public var setter:Null<FieldPropertyAccess> = null;
}
@:structInit
@@ -156,6 +157,7 @@ class Interp {
var isBypassAccessor:Bool = false;
var isPrivateAccess:Bool = false;
//var isVar:Bool = false;
public var importEnabled:Bool = true;
@@ -379,6 +381,7 @@ class Interp {
setVar(id, v);
}
} else {
// TODO: call "set_" if available
l.r = v;
if (l.depth == 0) {
setVar(id, v);
@@ -509,6 +512,7 @@ class Interp {
}
else {
var l = locals.get(id);
// TODO: call "set_" if available
l.r = v;
if (l.depth == 0) {
setVar(id, v);
@@ -568,6 +572,7 @@ class Interp {
switch (e) {
case EIdent(id):
var l = locals.get(id);
// TODO: call "set_" if available
if(l != null) {
var v:Dynamic = l.r;
if (prefix) {
@@ -725,6 +730,7 @@ class Interp {
if (locals.exists(id)) {
var l = locals.get(id);
// TODO: call get or set if available.
if(l != null)
return l.r;
}
@@ -1024,8 +1030,19 @@ class Interp {
case EIdent(id):
return resolve(id);
case EVar(n, _, e, isPublic, isStatic, _, isFinal, _, getter, setter):
if(depth > 0 && (getter != null || setter != null)) {
error(ECustom("Property Accessor for local variables is not allowed"));
return null;
}
declared.push({n: n, old: locals.get(n), depth: depth});
locals.set(n, {r: (e == null) ? null : expr(e), depth: depth});
var declVar:DeclaredVar = {
r: (e == null) ? null : expr(e),
depth: depth,
isFinal: isFinal,
getter: getter,
setter: setter
};
locals.set(n, declVar);
if (depth == 0) {
if(allowStaticVariables && isStatic == true) {
if(!staticVariables.exists(n)) // make it so it only sets it once
@@ -1394,6 +1411,7 @@ class Interp {
return val;
case EMeta(a, b, e):
var val:Dynamic = null;
switch(a) {
case ":bypassAccessor":
var oldAccessor = isBypassAccessor;
@@ -1408,6 +1426,9 @@ class Interp {
isPrivateAccess = oldPrivate;
return val;
}
val = expr(e);
return val;
/*
var oldAccessor = isBypassAccessor;
if(a == ":bypassAccessor") {
@@ -1418,7 +1439,6 @@ class Interp {
isBypassAccessor = oldAccessor;
return val;
*/
return val;
case ECheckType(e, _):
return expr(e);
case EUsing(name):
+44 -14
View File
@@ -103,6 +103,8 @@ class Parser {
var disableOrOp : Bool = false;
var isVar : Bool = false;
#if hscriptPos
var origin : String;
var tokenMin : Int;
@@ -857,16 +859,20 @@ 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
if( tk == TPOpen && id != "final" ) {
if( tk == TPOpen) {
if( id == "final" )
unexpected(tk);
var getId = getIdent();
switch (getId) {
case 'default': // Do nothing
case 'get': get = AGet;
case 'null': get = ANull;
case 'dynamic': get = ADynamic;
case 'never': get = ANever;
default: unexpected(TId(getId));
default: error(ECustom("Custom property accessor is not supported"), p1, tokenMax);
}
ensure(TComma);
var setId = getIdent();
@@ -874,8 +880,9 @@ class Parser {
case 'default': // Do nothing
case 'set': set = ASet;
case 'null': set = ANull;
case 'dynamic': set = ADynamic;
case 'never': set = ANever;
default: unexpected(TId(getId));
default: error(ECustom("Custom property accessor is not supported"), p1, tokenMax);
}
ensure(TPClose);
@@ -898,8 +905,8 @@ class Parser {
else
push(tk);
if(hasGetSet && (e == null || (allowTypes && t == null)))
error(ECustom("Property requires type-hint or initialization"), p1, tokenMax);
if(hasGetSet)
checkAccess(get, set, e, t);
nextType = null;
mk(EVar(ident, t, e, nextIsPublic, nextIsStatic, nextIsPrivate, id == "final", nextIsInline, get, set), p1, (e == null) ? tokenMax : pmax(e));
@@ -1604,6 +1611,24 @@ class Parser {
return args;
}
function checkAccess(get:FieldPropertyAccess, set:FieldPropertyAccess, ?expr:Expr, ?type:CType) {
#if hscriptPos
var p1 = tokenMin;
#end
switch([get, set]) {
case [AGet, ASet] | [AGet, ANever] | [ANever, ASet]:
if(expr != null && !isVar)
error(ECustom("Attempt to assign on field that is not a real variable"), p1, pmax(expr));
else if(type == null)
error(ECustom("Property requires type-hint"), p1, tokenMax);
case [ANever, ANever]:
error(ECustom("Unsupported property combination"), p1, (expr == null) ? tokenMax : pmax(expr));
default:
if(expr == null && type == null)
error(ECustom("Property requires type-hint or initialization"), p1, tokenMax);
}
}
// ------------------------ module -------------------------------
public function parseModule( content : String, ?origin : String = "hscript" ):Array<ModuleDecl> {
@@ -1812,15 +1837,19 @@ class Parser {
var name = getIdent();
var get = ADefault, set = ADefault;
var hasGetSet:Bool = false;
// TODO: throw "Missing ;" if tried to use (get, set) on final
if(maybe(TPOpen) && id != "final") {
if(maybe(TPOpen)) {
if(id == "final")
unexpected(TPOpen);
var getId = getIdent();
switch(getId) {
case 'default': // Do nothing
case 'get': get = AGet;
case 'null': get = ANull;
case 'dynamic': get = ADynamic;
case 'never': get = ANever;
default: unexpected(TId(getId));
default: error(ECustom("Custom property accessor is not supported"), tokenMin, tokenMax);
}
ensure(TComma);
var setId = getIdent();
@@ -1828,17 +1857,18 @@ class Parser {
case 'default': // Do nothing
case 'set': set = ASet;
case 'null': set = ANull;
case 'dynamic': set = ADynamic;
case 'never': set = ANever;
default: unexpected(TId(getId));
default: error(ECustom("Custom property accessor is not supported"), tokenMin, tokenMax);
}
ensure(TPClose);
hasGetSet = true;
}
var type = maybe(TDoubleDot) ? parseType() : null;
var expr = maybe(TOp("=")) ? parseExpr() : null;
var type:Null<CType> = maybe(TDoubleDot) ? parseType() : null;
var expr:Null<Expr> = maybe(TOp("=")) ? parseExpr() : null;
if(hasGetSet && (expr == null || type == null))
error(ECustom("Property requires type-hint or initialization"), p1, tokenMax);
if(hasGetSet)
checkAccess(get, set, expr, type);
if( expr != null ) {
if( isBlock(expr) )