From ab18c9c199bc4546c6be651991efdadba805dcad Mon Sep 17 00:00:00 2001 From: Ne_Eo Date: Fri, 27 Sep 2024 02:12:52 +0200 Subject: [PATCH 1/9] Small changes --- crowplexus/hscript/Printer.hx | 24 ++++++++++++------------ crowplexus/hscript/Tools.hx | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crowplexus/hscript/Printer.hx b/crowplexus/hscript/Printer.hx index f2acefb..ba49247 100644 --- a/crowplexus/hscript/Printer.hx +++ b/crowplexus/hscript/Printer.hx @@ -32,24 +32,24 @@ class Printer { public function new() {} - public function exprToString(e: Expr) { + public function exprToString(e: Expr): String { buf = new StringBuf(); tabs = ""; expr(e); return buf.toString(); } - public function typeToString(t: CType) { + public function typeToString(t: CType): String { buf = new StringBuf(); tabs = ""; type(t); return buf.toString(); } - inline function add(s: T) + inline function add(s: T): Void buf.add(s); - public function typePath(tp: TypePath) { + public function typePath(tp: TypePath): Void { add(tp.pack.join(".")); if (tp.pack.length > 0) add("."); @@ -69,7 +69,7 @@ class Printer { } } - function type(t: CType) { + function type(t: CType): Void { switch (t) { case CTOpt(t): add('?'); @@ -147,21 +147,21 @@ class Printer { } } - function addType(t: CType) { + function addType(t: CType): Void { if (t != null) { add(" : "); type(t); } } - function addArgument(a: Argument) { + function addArgument(a: Argument): Void { if (a.opt) add("?"); add(a.name); addType(a.t); } - function expr(e: Expr) { + function expr(e: Expr): Void { if (e == null) { add("??NULL??"); return; @@ -466,19 +466,19 @@ class Printer { } } - inline function incrementIndent() { + inline function incrementIndent(): Void { tabs += indent; } - inline function decrementIndent() { + inline function decrementIndent(): Void { tabs = tabs.substr(indent.length); } - public static function toString(e: Expr) { + public static function toString(e: Expr): String { return new Printer().exprToString(e); } - public static function errorToString(e: Expr.Error, showPos: Bool = true) { + public static function errorToString(e: Expr.Error, showPos: Bool = true): String { var message = switch (#if hscriptPos e.e #else e #end) { case EInvalidChar(c): "Invalid character: '" + (StringTools.isEof(c) ? "EOF" : String.fromCharCode(c)) + "' (" + c + ")"; case EUnexpected(s): "Unexpected token: \"" + s + "\""; diff --git a/crowplexus/hscript/Tools.hx b/crowplexus/hscript/Tools.hx index 252d12b..8d5e100 100644 --- a/crowplexus/hscript/Tools.hx +++ b/crowplexus/hscript/Tools.hx @@ -25,7 +25,7 @@ package crowplexus.hscript; import crowplexus.hscript.Expr; class Tools { - public static function iter(e: Expr, f: Expr->Void) { + public static function iter(e: Expr, f: Expr->Void): Void { switch (expr(e)) { case EConst(_), EIdent(_): case EVar(_, _, e, _): @@ -108,7 +108,7 @@ class Tools { } } - public static function map(e: Expr, f: Expr->Expr) { + public static function map(e: Expr, f: Expr->Expr): Expr { var edef = switch (expr(e)) { case EConst(_), EIdent(_), EBreak, EContinue: expr(e); case EVar(n, t, e, c): EVar(n, t, if (e != null) f(e) else null, c); @@ -146,7 +146,7 @@ class Tools { return #if hscriptPos e.e #else e #end; } - public static inline function mk(e: ExprDef, p: Expr) { + public static inline function mk(e: ExprDef, p: Expr): Expr { #if hscriptPos return { e: e, From aaa8f9e1141e20506dc60e1a70409e446aee195c Mon Sep 17 00:00:00 2001 From: Ne_Eo Date: Fri, 27 Sep 2024 02:25:38 +0200 Subject: [PATCH 2/9] Added ignore revs file --- .git-blame-ignore-revs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..0e00110 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,6 @@ +# clang-format all + +# $ git config blame.ignoreRevsFile .git-blame-ignore-revs + +# reformatting +4587f5b778b080329e330c2daaad8b3d946e57db \ No newline at end of file From 2062df9a1ee63e50d3d161fe77dc02d26523aa48 Mon Sep 17 00:00:00 2001 From: crowplexus <45212377+crowplexus@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:20:36 -0400 Subject: [PATCH 3/9] fix unary operators --- crowplexus/hscript/Interp.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index 82c49fb..aeda017 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -262,7 +262,7 @@ class Interp { error(ECustom("Cannot reassign final, for constant expression -> " + id)); } } - if (l == null) { + if (l != null) { if (prefix) { v += delta; setTo(v); From b4e882b23c21d6529ae17b9ad94f4358d7231b8b Mon Sep 17 00:00:00 2001 From: emily <84390581+inky03@users.noreply.github.com> Date: Sun, 13 Oct 2024 20:29:15 -0600 Subject: [PATCH 4/9] stirng interpolation and key->value iter oh dear --- crowplexus/hscript/Expr.hx | 6 +- crowplexus/hscript/Interp.hx | 58 ++++++++++++--- crowplexus/hscript/Parser.hx | 135 ++++++++++++++++++++++++++++++---- crowplexus/hscript/Printer.hx | 6 +- crowplexus/hscript/Tools.hx | 4 +- 5 files changed, 179 insertions(+), 30 deletions(-) diff --git a/crowplexus/hscript/Expr.hx b/crowplexus/hscript/Expr.hx index b15fec8..f493d8d 100644 --- a/crowplexus/hscript/Expr.hx +++ b/crowplexus/hscript/Expr.hx @@ -27,7 +27,7 @@ import crowplexus.hscript.Types.ByteUInt; enum Const { CInt(v: Int); CFloat(f: Float); - CString(s: String); + CString(s: String, ?interp: Bool); #if !haxe3 CInt32(v:haxe.Int32); #end @@ -72,7 +72,7 @@ enum Expr ECall(e:Expr, params:Array); EIf(cond:Expr, e1:Expr, ?e2:Expr); EWhile(cond:Expr, e:Expr); - EFor(v:String, it:Expr, e:Expr); + EFor(i:String, v:Null, it:Expr, e:Expr); EBreak; EContinue; EFunction(args:Array, e:Expr, ?name:String, ?ret:CType); @@ -166,10 +166,12 @@ enum Error EUnterminatedComment; EInvalidPreprocessor(msg:String); EUnknownVariable(v:String); + EInvalidKVIterator(v:String); EInvalidIterator(v:String); EInvalidOp(op:String); EInvalidAccess(f:String); ECustom(msg:String); + EEmptyExpression; } enum ModuleDecl { DPackage(path: Array); diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index aeda017..b089e00 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -262,12 +262,11 @@ class Interp { error(ECustom("Cannot reassign final, for constant expression -> " + id)); } } - if (l != null) { - if (prefix) { - v += delta; - setTo(v); - } else - setTo(v + delta); + if (prefix) { + v += delta; + setTo(v); + } else { + setTo(v + delta); } return v; case EField(e, f, s): @@ -494,8 +493,8 @@ class Interp { case EDoWhile(econd, e): doWhileLoop(econd, e); return null; - case EFor(v, it, e): - forLoop(v, it, e); + case EFor(i, v, it, e): + forLoop(i, v, it, e); return null; case EBreak: throw SBreak; @@ -811,15 +810,52 @@ class Interp { error(EInvalidIterator(v)); return v; } + function makeKVIterator(v: Dynamic): Null> { + #if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0')) + if (v.keyValueIterator != null) { + return v.keyValueIterator(); + } else { + if (v.iterator != null) { + v = v.iterator(); + } + } + #else + try { + return v.keyValueIterator(); + } catch (e:Dynamic) { + try { + v = v.iterator(); + } catch (e:Dynamic) {}; + }; + #end + if (v.hasNext == null || v.next == null) + error(EInvalidKVIterator(v)); + return v; + } - function forLoop(n, it, e) { + function forLoop(n, v, itExpr, e) { var old = declared.length; declared.push({n: n, old: locals.get(n)}); - var it = makeIterator(expr(it)); + var keyValue:Bool = false; + if (v != null) { + keyValue = true; + declared.push({n: v, old: locals.get(v)}); + } + var it = (keyValue ? makeKVIterator : makeIterator)(expr(itExpr)); var _itHasNext = it.hasNext; var _itNext = it.next; while (_itHasNext()) { - locals.set(n, {r: _itNext(), const: false}); + if (keyValue) { + var next = _itNext(); + if (next.key == null || next.value == null) { + var nulled:String = (next.key == null ? 'key' : 'value'); + error(ECustom('${Std.isOfType(next, Int) ? 'Int' : Type.getClassName(Type.getClass(next))} has no field $nulled')); + } + locals.set(n, {r: next.key, const: false}); + locals.set(v, {r: next.value, const: false}); + } else { + locals.set(n, {r: _itNext(), const: false}); + } try { expr(e); } catch (err:Stop) { diff --git a/crowplexus/hscript/Parser.hx b/crowplexus/hscript/Parser.hx index c39ccad..926e1c1 100644 --- a/crowplexus/hscript/Parser.hx +++ b/crowplexus/hscript/Parser.hx @@ -321,7 +321,7 @@ class Parser { case EUnop(_, prefix, e): !prefix && isBlock(e); case EWhile(_, e): isBlock(e); case EDoWhile(_, e): isBlock(e); - case EFor(_, _, e): isBlock(e); + case EFor(_, _, _, e): isBlock(e); case EReturn(e): e != null && isBlock(e); case ETry(_, _, _, e): isBlock(e); case EMeta(_, _, e): isBlock(e); @@ -365,7 +365,7 @@ class Parser { if (!allowJSON) unexpected(tk); switch (c) { - case CString(s): id = s; + case CString(s, _): id = s; default: unexpected(tk); } case TBrClose: @@ -388,6 +388,69 @@ class Parser { return parseExprNext(mk(EObject(fl), p1)); } + function interpolateString(s:String) { + var exprs = []; + var dollarPos:Int = s.indexOf('$'); + while (dollarPos > -1) { + var pos:Int = dollarPos; + var pre:String = s.substr(0, pos); + var next:String = s.charAt(++ pos); + if (next == '{') { + if (pre != '') exprs.push(mk(EConst(CString(pre)))); + var exprStr:String = ''; + var depth:Int = 1; + while (true) { + next = s.charAt(++ pos); + if (next == '{') { + depth ++; + } else if (next == '}') { + depth --; + } + if (depth < 1) break; + if (pos >= s.length) { + error(EUnterminatedString, pos, pos); + } + exprStr += next; + } + if (exprStr.trim() == '') { + error(EEmptyExpression, pos, pos); + } + var prevChar = char; + var prevInput = input; + var prevReadPos = readPos; // a bit stupid innit??? + var expr = parseString('($exprStr)' #if hscriptPos, origin #end); + readPos = prevReadPos; // rolling back parser state because otherwise we get problems... + input = prevInput; + char = prevChar; + exprs.push(expr); + pos ++; + } else if (next == '_' || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')) { + if (pre != '') exprs.push(mk(EConst(CString(pre)))); + var ident:String = ''; + while (next == '_' || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') || (next >= '0' && next <= '9')) { + ident += next; + next = s.charAt(++ pos); + } + exprs.push(mk(EIdent(ident))); + } else if (next == '$') { + exprs.push(mk(EConst(CString(pre + '$')))); + } + s = s.substr(pos ++); + dollarPos = s.indexOf('$'); + } + if (exprs.length == 0) { + return mk(EConst(CString(s))); + } else { + exprs.push(mk(EConst(CString(s)))); + var expr = exprs[0]; + for (i => nextExpr in exprs) { + if (i == 0) continue; + // NOTE: probably look into const optimization if possible, cause i really couldnt figure it out + expr = mk(EBinop('+', expr, nextExpr)); + } + return expr; + } + } function parseExpr() { var tk = token(); #if hscriptPos @@ -400,6 +463,12 @@ class Parser { e = mk(EIdent(id)); return parseExprNext(e); case TConst(c): + switch (c) { + default: + case CString(s, interp): + if (interp) + return parseExprNext(interpolateString(s)); + } return parseExprNext(mk(EConst(c))); case TPOpen: tk = token(); @@ -574,8 +643,8 @@ class Parser { if (e == null) return null; var edef = switch (expr(e)) { - case EFor(v, it, e2): - EFor(v, it, mapCompr(tmp, e2)); + case EFor(i, v, it, e2): + EFor(i, v, it, mapCompr(tmp, e2)); case EWhile(cond, e2): EWhile(cond, mapCompr(tmp, e2)); case EDoWhile(cond, e2): @@ -670,12 +739,20 @@ class Parser { mk(EDoWhile(econd, e), p1, pmax(econd)); case "for": ensure(TPOpen); - var vname = getIdent(); - ensureToken(TId("in")); + var iname = getIdent(); + var vname = null; + var tk = token(); + switch (tk) { + case TOp("=>"): + vname = getIdent(); + ensureToken(TId("in")); + case TId("in"): + default: unexpected(tk); + } var eiter = parseExpr(); ensure(TPClose); var e = parseExpr(); - mk(EFor(vname, eiter, e), p1, pmax(e)); + mk(EFor(iname, vname, eiter, e), p1, pmax(e)); case "break": mk(EBreak); case "continue": mk(EContinue); case "else": unexpected(TId(id)); @@ -1480,7 +1557,7 @@ class Parser { return StringTools.fastCodeAt(input, readPos++); } - function readString(until) { + function readString(until, interpolate: Bool = false) { var c = 0; var b = new StringBuf(); var esc = false; @@ -1540,9 +1617,39 @@ class Parser { } } else if (c == 92) esc = true; - else if (c == until) + else if (c == until) { break; - else { + } else if (c == 36 && interpolate) { // brace for impact !! + b.addChar(c); + var next = readChar(); + if (next == 123) { + b.addChar(next); + var depth:Int = 0; + while (true) { + next = readChar(); + if (StringTools.isEof(next)) { + error(EUnterminatedString, p1, p1); + } + b.addChar(next); + if (next == "'".code) { + var nextStr:String = readString("'".code, true); + for (char in nextStr) { + b.addChar(char); + } + b.addChar("'".code); + next = readChar(); + b.addChar(next); + } + if (next == 125) { + depth --; + if (depth < 0) + break; + } + } + } else { + readPos --; + } + } else { if (c == 10) line++; b.addChar(c); @@ -1758,8 +1865,10 @@ class Parser { return TBkOpen; case "]".code: return TBkClose; - case "'".code, '"'.code: - return TConst(CString(readString(char))); + case "'".code: + return TConst(CString(readString(char, true), true)); + case '"'.code: + return TConst(CString(readString(char), false)); case "?".code: char = readChar(); if (char == ".".code) @@ -1986,7 +2095,7 @@ class Parser { return switch (c) { case CInt(v): Std.string(v); case CFloat(f): Std.string(f); - case CString(s): s; // TODO : escape + quote + case CString(s, _): s; // TODO : escape + quote #if !haxe3 case CInt32(v): Std.string(v); #end diff --git a/crowplexus/hscript/Printer.hx b/crowplexus/hscript/Printer.hx index ba49247..a79c7ad 100644 --- a/crowplexus/hscript/Printer.hx +++ b/crowplexus/hscript/Printer.hx @@ -278,8 +278,8 @@ class Printer { add(" while ( "); expr(cond); add(" )"); - case EFor(v, it, e): - add("for( " + v + " in "); + case EFor(i, v, it, e): + add("for( " + (v == null ? i : '$i => $v') + " in "); expr(it); add(" ) "); expr(e); @@ -484,8 +484,10 @@ class Printer { case EUnexpected(s): "Unexpected token: \"" + s + "\""; case EUnterminatedString: "Unterminated string"; case EUnterminatedComment: "Unterminated comment"; + case EEmptyExpression: "Expression cannot be empty"; case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")"; case EUnknownVariable(v): "Unknown variable: " + v; + case EInvalidKVIterator(v): "Invalid key-value iterator: " + v; case EInvalidIterator(v): "Invalid iterator: " + v; case EInvalidOp(op): "Invalid operator: " + op; case EInvalidAccess(f): "Invalid access to field " + f; diff --git a/crowplexus/hscript/Tools.hx b/crowplexus/hscript/Tools.hx index 8d5e100..edad18f 100644 --- a/crowplexus/hscript/Tools.hx +++ b/crowplexus/hscript/Tools.hx @@ -58,7 +58,7 @@ class Tools { case EDoWhile(c, e): f(c); f(e); - case EFor(_, it, e): + case EFor(_, _, it, e): f(it); f(e); case EBreak, EContinue: @@ -121,7 +121,7 @@ class Tools { case EIf(c, e1, e2): EIf(f(c), f(e1), if (e2 != null) f(e2) else null); case EWhile(c, e): EWhile(f(c), f(e)); case EDoWhile(c, e): EDoWhile(f(c), f(e)); - case EFor(v, it, e): EFor(v, f(it), f(e)); + case EFor(i, v, it, e): EFor(i, v, f(it), f(e)); case EFunction(args, e, name, t): EFunction(args, f(e), name, t); case EReturn(e): EReturn(if (e != null) f(e) else null); case EArray(e, i): EArray(f(e), f(i)); From 90fbae237fc1d384d4fdf8c7402c5fc5cf52f254 Mon Sep 17 00:00:00 2001 From: crowplexus <45212377+crowplexus@users.noreply.github.com.> Date: Thu, 24 Oct 2024 16:21:53 -0400 Subject: [PATCH 5/9] fix escaped strings --- crowplexus/hscript/Bytes.hx | 6 ++- crowplexus/hscript/Expr.hx | 4 +- crowplexus/hscript/Interp.hx | 5 ++- crowplexus/hscript/Parser.hx | 72 +++++++++++++++++++++++------------- tests/assets/strings.hx | 19 ++++++++++ tests/src/Main.hx | 41 +++++++++++++++++++- 6 files changed, 116 insertions(+), 31 deletions(-) create mode 100644 tests/assets/strings.hx diff --git a/crowplexus/hscript/Bytes.hx b/crowplexus/hscript/Bytes.hx index f451e13..8bad31e 100644 --- a/crowplexus/hscript/Bytes.hx +++ b/crowplexus/hscript/Bytes.hx @@ -423,8 +423,9 @@ class Bytes { doEncodeExprType(EDoWhile); doEncode(cond); doEncode(e); - case EFor(v, it, e): + case EFor(i, v, it, e): doEncodeExprType(EFor); + doEncodeString(i); doEncodeString(v); doEncode(it); doEncode(e); @@ -605,9 +606,10 @@ class Bytes { var cond = doDecode(); EDoWhile(cond, doDecode()); case EFor: + var i = doDecodeString(); var v = doDecodeString(); var it = doDecode(); - EFor(v, it, doDecode()); + EFor(i, v, it, doDecode()); case EBreak: EBreak; case EContinue: diff --git a/crowplexus/hscript/Expr.hx b/crowplexus/hscript/Expr.hx index f493d8d..95ada0b 100644 --- a/crowplexus/hscript/Expr.hx +++ b/crowplexus/hscript/Expr.hx @@ -56,6 +56,7 @@ class Expr { enum ExprDef #else typedef ExprDef = Expr; + enum Expr #end { @@ -91,6 +92,7 @@ enum Expr EEnum(name:String, fields:Array); EDirectValue(value:Dynamic); } + typedef Argument = {name: String, ?t: CType, ?opt: Bool, ?value: Expr}; typedef Metadata = Array<{name: String, params: Array}>; @@ -158,7 +160,6 @@ enum ErrorDef #else enum Error #end - { EInvalidChar(c:Int); EUnexpected(s:String); @@ -173,6 +174,7 @@ enum Error ECustom(msg:String); EEmptyExpression; } + enum ModuleDecl { DPackage(path: Array); DImport(path: Array, ?everything: Bool, ?as: String); diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index b089e00..76c8535 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -810,6 +810,7 @@ class Interp { error(EInvalidIterator(v)); return v; } + function makeKVIterator(v: Dynamic): Null> { #if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0')) if (v.keyValueIterator != null) { @@ -836,7 +837,7 @@ class Interp { function forLoop(n, v, itExpr, e) { var old = declared.length; declared.push({n: n, old: locals.get(n)}); - var keyValue:Bool = false; + var keyValue: Bool = false; if (v != null) { keyValue = true; declared.push({n: v, old: locals.get(v)}); @@ -848,7 +849,7 @@ class Interp { if (keyValue) { var next = _itNext(); if (next.key == null || next.value == null) { - var nulled:String = (next.key == null ? 'key' : 'value'); + var nulled: String = (next.key == null ? 'key' : 'value'); error(ECustom('${Std.isOfType(next, Int) ? 'Int' : Type.getClassName(Type.getClass(next))} has no field $nulled')); } locals.set(n, {r: next.key, const: false}); diff --git a/crowplexus/hscript/Parser.hx b/crowplexus/hscript/Parser.hx index 926e1c1..8344617 100644 --- a/crowplexus/hscript/Parser.hx +++ b/crowplexus/hscript/Parser.hx @@ -142,7 +142,20 @@ class Parser { ["&&"], ["||"], [ - "=", "+=", "-=", "*=", "/=", "%=", "??" + "=", "<<=", ">>=", ">>>=", "|=", "&=", "^=", "=>" + "=", + "+=", + "-=", + "*=", + "/=", + "%=", + "??" + "=", + "<<=", + ">>=", + ">>>=", + "|=", + "&=", + "^=", + "=>" ], ["->"] ]; @@ -388,25 +401,27 @@ class Parser { return parseExprNext(mk(EObject(fl), p1)); } - function interpolateString(s:String) { + function interpolateString(s: String) { var exprs = []; - var dollarPos:Int = s.indexOf('$'); + var dollarPos: Int = s.indexOf('$'); while (dollarPos > -1) { - var pos:Int = dollarPos; - var pre:String = s.substr(0, pos); - var next:String = s.charAt(++ pos); + var pos: Int = dollarPos; + var pre: String = s.substr(0, pos); + var next: String = s.charAt(++pos); if (next == '{') { - if (pre != '') exprs.push(mk(EConst(CString(pre)))); - var exprStr:String = ''; - var depth:Int = 1; + if (pre != '') + exprs.push(mk(EConst(CString(pre)))); + var exprStr: String = ''; + var depth: Int = 1; while (true) { - next = s.charAt(++ pos); + next = s.charAt(++pos); if (next == '{') { - depth ++; + depth++; } else if (next == '}') { - depth --; + depth--; } - if (depth < 1) break; + if (depth < 1) + break; if (pos >= s.length) { error(EUnterminatedString, pos, pos); } @@ -423,19 +438,25 @@ class Parser { input = prevInput; char = prevChar; exprs.push(expr); - pos ++; + pos++; } else if (next == '_' || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')) { - if (pre != '') exprs.push(mk(EConst(CString(pre)))); - var ident:String = ''; + if (pre != '') + exprs.push(mk(EConst(CString(pre)))); + var ident: String = ''; while (next == '_' || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') || (next >= '0' && next <= '9')) { ident += next; - next = s.charAt(++ pos); + next = s.charAt(++pos); } exprs.push(mk(EIdent(ident))); } else if (next == '$') { + var secondToNext: String = s.charAt(pos); + if (secondToNext == "$") { // if its another dollar, skip... + s = pre + s.substr(pos, pos + 1); // remove $ ahead of the current one + break; + } exprs.push(mk(EConst(CString(pre + '$')))); } - s = s.substr(pos ++); + s = s.substr(pos++); dollarPos = s.indexOf('$'); } if (exprs.length == 0) { @@ -444,13 +465,15 @@ class Parser { exprs.push(mk(EConst(CString(s)))); var expr = exprs[0]; for (i => nextExpr in exprs) { - if (i == 0) continue; + if (i == 0) + continue; // NOTE: probably look into const optimization if possible, cause i really couldnt figure it out expr = mk(EBinop('+', expr, nextExpr)); } return expr; } } + function parseExpr() { var tk = token(); #if hscriptPos @@ -466,8 +489,7 @@ class Parser { switch (c) { default: case CString(s, interp): - if (interp) - return parseExprNext(interpolateString(s)); + if (interp) return parseExprNext(interpolateString(s)); } return parseExprNext(mk(EConst(c))); case TPOpen: @@ -1624,7 +1646,7 @@ class Parser { var next = readChar(); if (next == 123) { b.addChar(next); - var depth:Int = 0; + var depth: Int = 0; while (true) { next = readChar(); if (StringTools.isEof(next)) { @@ -1632,7 +1654,7 @@ class Parser { } b.addChar(next); if (next == "'".code) { - var nextStr:String = readString("'".code, true); + var nextStr: String = readString("'".code, true); for (char in nextStr) { b.addChar(char); } @@ -1641,13 +1663,13 @@ class Parser { b.addChar(next); } if (next == 125) { - depth --; + depth--; if (depth < 0) break; } } } else { - readPos --; + readPos--; } } else { if (c == 10) diff --git a/tests/assets/strings.hx b/tests/assets/strings.hx new file mode 100644 index 0000000..f085ce7 --- /dev/null +++ b/tests/assets/strings.hx @@ -0,0 +1,19 @@ +function main() { + trace('Program Start!'); + + var hello = "Hello!"; + trace('test 1, basic interpolation: $hello'); + var tally = { + score: 10, + hits: 5, + misses: 0, + }; + var stats = 'Score:${tally.score}'; + trace('test 2, bracket interpolation: ' + stats); + stats = 'Score:${tally.score} - Hits:${tally.hits} - Misses:${tally.misses}'; + trace('test 3, bracket interpolation with multiple strings: ' + stats); + + trace('test 4, escaped interpolation: $${caw}, also blablablablabla'); + + trace('test 5, nested interpolation: ${'${tally.score}'}'); +} diff --git a/tests/src/Main.hx b/tests/src/Main.hx index 732a31b..fb45a97 100644 --- a/tests/src/Main.hx +++ b/tests/src/Main.hx @@ -13,9 +13,10 @@ using StringTools; @:access(crowplexus.iris.Iris) class Main { static function main() { - mainTest(); + // mainTest(); // mainBytes(); // testIndenticalNames(); + testStringInterpolation(); } /** @@ -111,6 +112,44 @@ class Main { trace(tokens); } } + + static function testStringInterpolation() { + function testFile() { // FILE TEST + trace('Testing String Interpolation, with a file'); + var file: String = sys.io.File.getContent("./assets/strings.hx"); + var script: Iris = new Iris(file, {name: "StringInterpolationTest"}); + script.call("main", []); + } + function testPureString() { // STRING TEST + trace('...With a pure string'); + var source: String = "function main() { + trace('Program Start!'); + + var hello = 'Hello!'; + + trace('test 1, basic interpolation: $hello'); + var tally = { + score: 10, + hits: 5, + misses: 0, + }; + var stats = 'Score:${tally.score}'; + trace('test 2, bracket interpolation: $stats'); + stats = 'Score:${tally.score} - Hits:${tally.hits} - Misses:${tally.misses}'; + trace('test 3, bracket interpolation with multiple strings: $stats'); + + trace('test 4, escaped interpolation: $${caw}'); + + trace('test 5, nested interpolation: ${'${tally.score}'}'); + }"; + var source: Iris = new Iris(source, {name: "StringInterpolationTestSource", autoRun: false}); + source.execute(); + source.call("main", []); + } + + testFile(); + // testPureString(); + } } enum Test { From 7c0de31fb252e40ce9d0a711428ead6069c2d3f9 Mon Sep 17 00:00:00 2001 From: Ne_Eo Date: Sat, 28 Dec 2024 01:59:57 +0100 Subject: [PATCH 6/9] function.bind() support --- crowplexus/hscript/Interp.hx | 52 +++++++++++++++++++++++++++++------- crowplexus/iris/Iris.hx | 7 ++++- tests/assets/bind.hx | 22 +++++++++++++++ tests/build-generic.hxml | 1 + tests/src/Main.hx | 21 ++++++++++----- 5 files changed, 86 insertions(+), 17 deletions(-) create mode 100644 tests/assets/bind.hx diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index 1f8259e..4af63ee 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -22,6 +22,7 @@ package crowplexus.hscript; +import haxe.Constraints.Function; import Type.ValueType; import crowplexus.hscript.Expr; import crowplexus.hscript.Tools; @@ -472,19 +473,50 @@ class Interp { null; } case ECall(e, params): - var args = new Array(); - for (p in params) - args.push(expr(p)); - switch (Tools.expr(e)) { case EField(e, f, s): - var obj = expr(e); - if (obj == null) - if (!s) - error(EInvalidAccess(f)); - return fcall(obj, f, args); + var obj: Dynamic = expr(e); + + if (obj == null) { + if (s == true) + return null; + error(EInvalidAccess(f)); + } + + if (f == "bind" && Reflect.isFunction(obj)) { + var obj: Function = obj; + if (params.length == 0) { // Special case for function.bind() + return Reflect.makeVarArgs(function(ar: Array) { + return obj(); + }); + } + + // bind(_, false) => function(a1) return obj(a1, false); + // bind(false, _) => function(a2) return obj(false, a2); + // bind(_, _) => function(a1, a2) return obj(a1, a2); + + var args = []; + for (p in params) { + switch (Tools.expr(p)) { + case EIdent(_): + args.push(null); + default: + args.push(p); + } + } + var me = this; + // TODO: make it increment the depth? + return Reflect.makeVarArgs(function(ar: Array) { + var i = 0; + var actualArgs = [for (a in args) if (a != null) me.expr(a) else ar[i++]]; + return Reflect.callMethod(null, obj, actualArgs); + }); + } + + return fcall(obj, f, [for (p in params) expr(p)]); default: - return call(null, expr(e), args); + var field = expr(e); + return call(null, field, [for (p in params) expr(p)]); } case EIf(econd, e1, e2): return if (expr(econd) == true) expr(e1) else if (e2 == null) null else expr(e2); diff --git a/crowplexus/iris/Iris.hx b/crowplexus/iris/Iris.hx index 6c013d9..87cb976 100644 --- a/crowplexus/iris/Iris.hx +++ b/crowplexus/iris/Iris.hx @@ -1,5 +1,6 @@ package crowplexus.iris; +import haxe.CallStack; import crowplexus.iris.utils.Ansi; import crowplexus.hscript.proxy.ProxyType; import haxe.ds.StringMap; @@ -372,7 +373,11 @@ class Iris { #end catch (e:haxe.Exception) { var pos = isFunction ? this.interp.posInfos() : Iris.getDefaultPos(this.name); - Iris.error(Std.string(e), pos); + Iris.error( + Std.string(e) + #if IRIS_DEBUG + "\n" + CallStack.toString(CallStack.exceptionStack(true)) #end, + pos + ); } // @formatter:on return null; diff --git a/tests/assets/bind.hx b/tests/assets/bind.hx new file mode 100644 index 0000000..0f0e246 --- /dev/null +++ b/tests/assets/bind.hx @@ -0,0 +1,22 @@ +function main() { + trace("Hello World!"); + + function test(a: Int, b: Int) { + trace(a + b); + } + + var test2 = test.bind(1, _); + test2(2); + + var test3 = test.bind(1, _); + test3(2); + + var test4 = test.bind(_, 2); + test4(1); + + var test5 = test.bind(_, _); + test5(1, 2); + + var test5 = test.bind(_, "hello"); + test5(1, 2); +} diff --git a/tests/build-generic.hxml b/tests/build-generic.hxml index 7701093..300251f 100644 --- a/tests/build-generic.hxml +++ b/tests/build-generic.hxml @@ -22,5 +22,6 @@ --resource assets/using.hx@assets/using.hx --resource assets/bytes.hx@assets/bytes.hx --resource assets/test.hx@assets/test.hx +--resource assets/bind.hx@assets/bind.hx ../extraParams.hxml diff --git a/tests/src/Main.hx b/tests/src/Main.hx index 8896c5b..9c96528 100644 --- a/tests/src/Main.hx +++ b/tests/src/Main.hx @@ -17,12 +17,10 @@ class Main { // mainTest(); // mainBytes(); // testIndenticalNames(); -<<<<<<< HEAD // testStringInterpolation(); - testStringTools(); -======= - testUsing(); ->>>>>>> def329241c94ff5185f4388592f1288217453e1e + // fullTestParseEntireSourceCode(); + // testUsing(); + testBind(); } /** @@ -78,7 +76,6 @@ class Main { // var printer = new Printer(); // trace(printer.exprToString(myScript.expr)); - // fullTestParseEntireSourceCode() } /* @@ -168,6 +165,18 @@ class Main { source.call("main", []); } } + + /** + * Test for Hscript - function.bind() + */ + static function testBind() { + var myScript: Iris = new Iris(Resource.getString("assets/bind.hx"), { + name: "bind", + autoRun: false + }); + myScript.execute(); + myScript.call("main"); + } } enum Test { From 62d828b5f9100867bb30becd5c9fa251b138ba1a Mon Sep 17 00:00:00 2001 From: Ne_Eo Date: Sat, 28 Dec 2024 02:04:24 +0100 Subject: [PATCH 7/9] small error check for .bind --- crowplexus/hscript/Interp.hx | 4 ++++ tests/assets/bind.hx | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index 4af63ee..fbe262c 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -495,11 +495,13 @@ class Interp { // bind(false, _) => function(a2) return obj(false, a2); // bind(_, _) => function(a1, a2) return obj(a1, a2); + var totalNeeded = 0; var args = []; for (p in params) { switch (Tools.expr(p)) { case EIdent(_): args.push(null); + totalNeeded++; default: args.push(p); } @@ -507,6 +509,8 @@ class Interp { var me = this; // TODO: make it increment the depth? return Reflect.makeVarArgs(function(ar: Array) { + if (ar.length < totalNeeded) + error(ECustom("Too few arguments")); // TODO: make it say like "Not enough arguments, expected a:Int" var i = 0; var actualArgs = [for (a in args) if (a != null) me.expr(a) else ar[i++]]; return Reflect.callMethod(null, obj, actualArgs); diff --git a/tests/assets/bind.hx b/tests/assets/bind.hx index 0f0e246..37ac67d 100644 --- a/tests/assets/bind.hx +++ b/tests/assets/bind.hx @@ -17,6 +17,11 @@ function main() { var test5 = test.bind(_, _); test5(1, 2); - var test5 = test.bind(_, "hello"); - test5(1, 2); + try { + var test5 = test.bind(_, 4); + test5(); + trace("Should have thrown an error"); + } catch (e:Dynamic) { + trace(e); + } } From 8e9cb66f62ad0b5b7f7415061af69c3c0679f07d Mon Sep 17 00:00:00 2001 From: bananaTiko <111482265+bananaTiko@users.noreply.github.com> Date: Fri, 26 Sep 2025 19:06:17 -0700 Subject: [PATCH 8/9] Push PsychExtendedThings/hscript-iris into Untitled-Psych-Fork/hscript-iris-UPF (#7) * scriptObject (Direct Access to State/Substate.instance) and Some Changes IG * Some Updates --------- Co-authored-by: Prohack101010 --- crowplexus/hscript/IHScriptCustomBehaviour.hx | 6 + crowplexus/hscript/Interp.hx | 124 +++++++++++++++--- crowplexus/hscript/Parser.hx | 16 ++- 3 files changed, 124 insertions(+), 22 deletions(-) create mode 100644 crowplexus/hscript/IHScriptCustomBehaviour.hx diff --git a/crowplexus/hscript/IHScriptCustomBehaviour.hx b/crowplexus/hscript/IHScriptCustomBehaviour.hx new file mode 100644 index 0000000..570bb0b --- /dev/null +++ b/crowplexus/hscript/IHScriptCustomBehaviour.hx @@ -0,0 +1,6 @@ +package crowplexus.hscript; + +interface IHScriptCustomBehaviour { + public function hset(name:String, val:Dynamic):Dynamic; + public function hget(name:String):Dynamic; +} \ No newline at end of file diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index fbe262c..d5d065e 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -25,11 +25,14 @@ package crowplexus.hscript; import haxe.Constraints.Function; import Type.ValueType; import crowplexus.hscript.Expr; +import crowplexus.hscript.IHScriptCustomBehaviour; import crowplexus.hscript.Tools; import crowplexus.iris.Iris; import crowplexus.iris.IrisUsingClass; import crowplexus.iris.utils.UsingEntry; import haxe.Constraints.IMap; +import haxe.EnumTools; +import haxe.display.Protocol.InitializeResult; import haxe.PosInfos; private enum Stop { @@ -51,6 +54,12 @@ class DeclaredVar { } class Interp { + public var scriptObject(default, set):Dynamic; + public function set_scriptObject(v:Dynamic) { + __instanceFields = Type.getInstanceFields(Type.getClass(v)); + return scriptObject = v; + } + #if haxe3 public var variables: Map; public var imports: Map; @@ -70,6 +79,7 @@ class Interp { var declared: Array; var returnValue: Dynamic; + var __instanceFields:Array = []; #if hscriptPos var curExpr: Expr; #end @@ -171,9 +181,23 @@ class Interp { switch (Tools.expr(e1)) { case EIdent(id): var l = locals.get(id); - if (l == null) - setVar(id, v) - else { + if (l == null) { + if (!variables.exists(id) && scriptObject != null) { + if (Type.typeof(scriptObject) == TObject) { + Reflect.setField(scriptObject, id, v); + } else { + if (__instanceFields.contains(id)) { + Reflect.setProperty(scriptObject, id, v); + } else if (__instanceFields.contains('set_$id')) { // setter + Reflect.getProperty(scriptObject, 'set_$id')(v); + } else { + setVar(id, v); + } + } + } else { + setVar(id, v); + } + } else { if (l.const != true) l.r = v; else @@ -213,8 +237,15 @@ class Interp { case EIdent(id): var l = locals.get(id); v = fop(expr(e1), expr(e2)); - if (l == null) - setVar(id, v) + if (l == null) { + if (__instanceFields.contains(id)) { + Reflect.setProperty(scriptObject, id, v); + } else if (__instanceFields.contains('set_$id')) { // setter + Reflect.getProperty(scriptObject, 'set_$id')(v); + } else { + setVar(id, v); + } + } else { if (l.const != true) l.r = v; @@ -387,6 +418,7 @@ class Interp { var l = locals.get(id); return l.r; } + var vars = variables.get(id); if (variables.exists(id)) { var v = variables.get(id); @@ -398,6 +430,23 @@ class Interp { return v; } + if (vars == null && !variables.exists(id)) { + if (scriptObject != null) { + // search in object + if (id == "this") { + return scriptObject; + } else if ((Type.typeof(scriptObject) == TObject) && Reflect.hasField(scriptObject, id)) { + return Reflect.field(scriptObject, id); + } else { + if (__instanceFields.contains(id)) { + return Reflect.getProperty(scriptObject, id); + } else if (__instanceFields.contains('get_$id')) { // getter + return Reflect.getProperty(scriptObject, 'get_$id')(); + } + } + } + } + error(EUnknownVariable(id)); return null; @@ -923,28 +972,63 @@ class Interp { cast(map, IMap).set(key, value); } + public static var getRedirects:MapString->Dynamic> = []; + public static var setRedirects:MapString->Dynamic->Dynamic> = []; + function get(o: Dynamic, f: String): Dynamic { if (o == null) error(EInvalidAccess(f)); return { - #if php - // https://github.com/HaxeFoundation/haxe/issues/4915 - try { - Reflect.getProperty(o, f); - } catch (e:Dynamic) { - Reflect.field(o, f); - } - #else - Reflect.getProperty(o, f); - #end + var redirect:Dynamic->String->Dynamic = null; + var cl:String = switch(Type.typeof(o)) { + case TNull: + "Null"; + case TInt: + "Int"; + case TFloat: + "Float"; + case TBool: + "Bool"; + case _: + null; + }; + if (getRedirects.exists(cl = Type.getClassName(Type.getClass(o))) && (redirect = getRedirects[cl]) != null) { + return redirect(o, f); + } else if (o is IHScriptCustomBehaviour) { + var obj = cast(o, IHScriptCustomBehaviour); + return obj.hget(f); + } else { + var v = null; + if ((v = Reflect.getProperty(o, f)) == null) v = Reflect.getProperty(Type.getClass(o), f); + return v; + } } } function set(o: Dynamic, f: String, v: Dynamic): Dynamic { - if (o == null) - error(EInvalidAccess(f)); - Reflect.setProperty(o, f, v); - return v; + if( o == null ) error(EInvalidAccess(f)); + + var redirect:Dynamic->String->Dynamic->Dynamic = null; + var cl:String = switch(Type.typeof(o)) { + case TNull: + "Null"; + case TInt: + "Int"; + case TFloat: + "Float"; + case TBool: + "Bool"; + case _: + null; + }; + if (setRedirects.exists(cl = Type.getClassName(Type.getClass(o))) && (redirect = setRedirects[cl]) != null) + return redirect(o, f, v); + if (o is IHScriptCustomBehaviour) { + var obj = cast(o, IHScriptCustomBehaviour); + return obj.hset(f, v); + } + Reflect.setProperty(o,f,v); + return v; } /** @@ -1068,4 +1152,4 @@ class Interp { c = resolve(cl); return Type.createInstance(c, args); } -} +} \ No newline at end of file diff --git a/crowplexus/hscript/Parser.hx b/crowplexus/hscript/Parser.hx index 9803e43..355d9e7 100644 --- a/crowplexus/hscript/Parser.hx +++ b/crowplexus/hscript/Parser.hx @@ -78,10 +78,10 @@ class Parser { /** allows to check for #if / #else in code **/ - public var preprocesorValues: Map = new Map(); + public var preprocessorValues : Map = new Map(); /** - activate JSON compatiblity + activate JSON compatibility **/ public var allowJSON: Bool; @@ -1302,6 +1302,14 @@ class Parser { fields.push({name: name, t: parseType(), meta: meta}); meta = null; ensure(TSemicolon); + case TId("final"): + var name = getIdent(); + ensure(TDoubleDot); + if( meta == null ) meta = []; + meta.push({ name : ":final", params : [] }); + fields.push( { name : name, t : parseType(), meta : meta } ); + meta = null; + ensure(TSemicolon); case TId(name): ensure(TDoubleDot); fields.push({name: name, t: parseType(), meta: meta}); @@ -2174,6 +2182,10 @@ class Parser { case TQuestionDot: "?."; } } + + @:noCompletion public var preprocesorValues(get,set) : Map; + inline function get_preprocesorValues() return this.preprocessorValues; + inline function set_preprocesorValues(v) return this.preprocessorValues = v; } @:structInit From 7e564d53bbc1862d814cc0d04cc532a0c5458ad3 Mon Sep 17 00:00:00 2001 From: bananaTiko <111482265+bananaTiko@users.noreply.github.com> Date: Fri, 26 Sep 2025 19:06:42 -0700 Subject: [PATCH 9/9] =?UTF-8?q?Revert=20"Push=20PsychExtendedThings/hscrip?= =?UTF-8?q?t-iris=20into=20Untitled-Psych-Fork/hscrip=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8e9cb66f62ad0b5b7f7415061af69c3c0679f07d. --- crowplexus/hscript/IHScriptCustomBehaviour.hx | 6 - crowplexus/hscript/Interp.hx | 124 +++--------------- crowplexus/hscript/Parser.hx | 16 +-- 3 files changed, 22 insertions(+), 124 deletions(-) delete mode 100644 crowplexus/hscript/IHScriptCustomBehaviour.hx diff --git a/crowplexus/hscript/IHScriptCustomBehaviour.hx b/crowplexus/hscript/IHScriptCustomBehaviour.hx deleted file mode 100644 index 570bb0b..0000000 --- a/crowplexus/hscript/IHScriptCustomBehaviour.hx +++ /dev/null @@ -1,6 +0,0 @@ -package crowplexus.hscript; - -interface IHScriptCustomBehaviour { - public function hset(name:String, val:Dynamic):Dynamic; - public function hget(name:String):Dynamic; -} \ No newline at end of file diff --git a/crowplexus/hscript/Interp.hx b/crowplexus/hscript/Interp.hx index d5d065e..fbe262c 100644 --- a/crowplexus/hscript/Interp.hx +++ b/crowplexus/hscript/Interp.hx @@ -25,14 +25,11 @@ package crowplexus.hscript; import haxe.Constraints.Function; import Type.ValueType; import crowplexus.hscript.Expr; -import crowplexus.hscript.IHScriptCustomBehaviour; import crowplexus.hscript.Tools; import crowplexus.iris.Iris; import crowplexus.iris.IrisUsingClass; import crowplexus.iris.utils.UsingEntry; import haxe.Constraints.IMap; -import haxe.EnumTools; -import haxe.display.Protocol.InitializeResult; import haxe.PosInfos; private enum Stop { @@ -54,12 +51,6 @@ class DeclaredVar { } class Interp { - public var scriptObject(default, set):Dynamic; - public function set_scriptObject(v:Dynamic) { - __instanceFields = Type.getInstanceFields(Type.getClass(v)); - return scriptObject = v; - } - #if haxe3 public var variables: Map; public var imports: Map; @@ -79,7 +70,6 @@ class Interp { var declared: Array; var returnValue: Dynamic; - var __instanceFields:Array = []; #if hscriptPos var curExpr: Expr; #end @@ -181,23 +171,9 @@ class Interp { switch (Tools.expr(e1)) { case EIdent(id): var l = locals.get(id); - if (l == null) { - if (!variables.exists(id) && scriptObject != null) { - if (Type.typeof(scriptObject) == TObject) { - Reflect.setField(scriptObject, id, v); - } else { - if (__instanceFields.contains(id)) { - Reflect.setProperty(scriptObject, id, v); - } else if (__instanceFields.contains('set_$id')) { // setter - Reflect.getProperty(scriptObject, 'set_$id')(v); - } else { - setVar(id, v); - } - } - } else { - setVar(id, v); - } - } else { + if (l == null) + setVar(id, v) + else { if (l.const != true) l.r = v; else @@ -237,15 +213,8 @@ class Interp { case EIdent(id): var l = locals.get(id); v = fop(expr(e1), expr(e2)); - if (l == null) { - if (__instanceFields.contains(id)) { - Reflect.setProperty(scriptObject, id, v); - } else if (__instanceFields.contains('set_$id')) { // setter - Reflect.getProperty(scriptObject, 'set_$id')(v); - } else { - setVar(id, v); - } - } + if (l == null) + setVar(id, v) else { if (l.const != true) l.r = v; @@ -418,7 +387,6 @@ class Interp { var l = locals.get(id); return l.r; } - var vars = variables.get(id); if (variables.exists(id)) { var v = variables.get(id); @@ -430,23 +398,6 @@ class Interp { return v; } - if (vars == null && !variables.exists(id)) { - if (scriptObject != null) { - // search in object - if (id == "this") { - return scriptObject; - } else if ((Type.typeof(scriptObject) == TObject) && Reflect.hasField(scriptObject, id)) { - return Reflect.field(scriptObject, id); - } else { - if (__instanceFields.contains(id)) { - return Reflect.getProperty(scriptObject, id); - } else if (__instanceFields.contains('get_$id')) { // getter - return Reflect.getProperty(scriptObject, 'get_$id')(); - } - } - } - } - error(EUnknownVariable(id)); return null; @@ -972,63 +923,28 @@ class Interp { cast(map, IMap).set(key, value); } - public static var getRedirects:MapString->Dynamic> = []; - public static var setRedirects:MapString->Dynamic->Dynamic> = []; - function get(o: Dynamic, f: String): Dynamic { if (o == null) error(EInvalidAccess(f)); return { - var redirect:Dynamic->String->Dynamic = null; - var cl:String = switch(Type.typeof(o)) { - case TNull: - "Null"; - case TInt: - "Int"; - case TFloat: - "Float"; - case TBool: - "Bool"; - case _: - null; - }; - if (getRedirects.exists(cl = Type.getClassName(Type.getClass(o))) && (redirect = getRedirects[cl]) != null) { - return redirect(o, f); - } else if (o is IHScriptCustomBehaviour) { - var obj = cast(o, IHScriptCustomBehaviour); - return obj.hget(f); - } else { - var v = null; - if ((v = Reflect.getProperty(o, f)) == null) v = Reflect.getProperty(Type.getClass(o), f); - return v; - } + #if php + // https://github.com/HaxeFoundation/haxe/issues/4915 + try { + Reflect.getProperty(o, f); + } catch (e:Dynamic) { + Reflect.field(o, f); + } + #else + Reflect.getProperty(o, f); + #end } } function set(o: Dynamic, f: String, v: Dynamic): Dynamic { - if( o == null ) error(EInvalidAccess(f)); - - var redirect:Dynamic->String->Dynamic->Dynamic = null; - var cl:String = switch(Type.typeof(o)) { - case TNull: - "Null"; - case TInt: - "Int"; - case TFloat: - "Float"; - case TBool: - "Bool"; - case _: - null; - }; - if (setRedirects.exists(cl = Type.getClassName(Type.getClass(o))) && (redirect = setRedirects[cl]) != null) - return redirect(o, f, v); - if (o is IHScriptCustomBehaviour) { - var obj = cast(o, IHScriptCustomBehaviour); - return obj.hset(f, v); - } - Reflect.setProperty(o,f,v); - return v; + if (o == null) + error(EInvalidAccess(f)); + Reflect.setProperty(o, f, v); + return v; } /** @@ -1152,4 +1068,4 @@ class Interp { c = resolve(cl); return Type.createInstance(c, args); } -} \ No newline at end of file +} diff --git a/crowplexus/hscript/Parser.hx b/crowplexus/hscript/Parser.hx index 355d9e7..9803e43 100644 --- a/crowplexus/hscript/Parser.hx +++ b/crowplexus/hscript/Parser.hx @@ -78,10 +78,10 @@ class Parser { /** allows to check for #if / #else in code **/ - public var preprocessorValues : Map = new Map(); + public var preprocesorValues: Map = new Map(); /** - activate JSON compatibility + activate JSON compatiblity **/ public var allowJSON: Bool; @@ -1302,14 +1302,6 @@ class Parser { fields.push({name: name, t: parseType(), meta: meta}); meta = null; ensure(TSemicolon); - case TId("final"): - var name = getIdent(); - ensure(TDoubleDot); - if( meta == null ) meta = []; - meta.push({ name : ":final", params : [] }); - fields.push( { name : name, t : parseType(), meta : meta } ); - meta = null; - ensure(TSemicolon); case TId(name): ensure(TDoubleDot); fields.push({name: name, t: parseType(), meta: meta}); @@ -2182,10 +2174,6 @@ class Parser { case TQuestionDot: "?."; } } - - @:noCompletion public var preprocesorValues(get,set) : Map; - inline function get_preprocesorValues() return this.preprocessorValues; - inline function set_preprocesorValues(v) return this.preprocessorValues = v; } @:structInit