Skip to content

Commit 4037123

Browse files
committed
finals but like actual finals
1 parent 27c86f9 commit 4037123

File tree

5 files changed

+44
-5
lines changed

5 files changed

+44
-5
lines changed

hscript/Expr.hx

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum Expr {
4343
EConst( c : Const );
4444
EIdent( v : String );
4545
EVar( n : String, ?t : CType, ?e : Expr );
46+
EFinal( n : String, ?t : CType, ?e : Expr );
4647
EParent( e : Expr );
4748
EBlock( e : Array<Expr> );
4849
EField( e : Expr, f : String );
@@ -174,4 +175,5 @@ typedef VarDecl = {
174175
var set : Null<String>;
175176
var expr : Null<Expr>;
176177
var type : Null<CType>;
178+
var isfinal : Null<Bool>;
177179
}

hscript/Interp.hx

+9-2
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ private enum Stop {
3333
class Interp {
3434

3535
public var variables : Map<String,Dynamic>;
36-
var locals : Map<String,{ r : Dynamic }>;
36+
var locals : Map<String,{ r : Dynamic, ?isfinal : Bool }>;
3737
var binops : Map<String, Expr -> Expr -> Dynamic >;
3838

3939
var depth : Int;
4040
var inTry : Bool;
41-
var declared : Array<{ n : String, old : { r : Dynamic } }>;
41+
var declared : Array<{ n : String, old : { r : Dynamic, ?isfinal : Bool } }>;
4242
var returnValue : Dynamic;
4343

4444
#if hscriptPos
@@ -122,6 +122,7 @@ class Interp {
122122
switch( Tools.expr(e1) ) {
123123
case EIdent(id):
124124
var l = locals.get(id);
125+
if( l != null && l.isfinal && l.r != null) return error(EInvalidAccess(id));
125126
if( l == null )
126127
setVar(id,v)
127128
else
@@ -155,6 +156,7 @@ class Interp {
155156
case EIdent(id):
156157
var l = locals.get(id);
157158
v = fop(expr(e1),expr(e2));
159+
if( l != null && l.isfinal && l.r != null) return error(EInvalidAccess(id));
158160
if( l == null )
159161
setVar(id,v)
160162
else
@@ -189,6 +191,7 @@ class Interp {
189191
case EIdent(id):
190192
var l = locals.get(id);
191193
var v : Dynamic = (l == null) ? resolve(id) : l.r;
194+
if( l != null && l.isfinal && l.r != null) return error(EInvalidAccess(id));
192195
if( prefix ) {
193196
v += delta;
194197
if( l == null ) setVar(id,v) else l.r = v;
@@ -311,6 +314,10 @@ class Interp {
311314
declared.push({ n : n, old : locals.get(n) });
312315
locals.set(n,{ r : (e == null)?null:expr(e) });
313316
return null;
317+
case EFinal(n,_,e):
318+
declared.push({ n : n, old : locals.get(n) });
319+
locals.set(n,{ r : (e == null)?null:expr(e), isfinal : true });
320+
return null;
314321
case EParent(e):
315322
return expr(e);
316323
case EBlock(exprs):

hscript/Parser.hx

+24-2
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ class Parser {
267267
return switch( expr(e) ) {
268268
case EBlock(_), EObject(_), ESwitch(_): true;
269269
case EFunction(_,e,_,_): isBlock(e);
270-
case EVar(_, t, e): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false;
270+
case EVar(_, t, e) | EFinal(_, t, e): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false;
271271
case EIf(_,e1,e2): if( e2 != null ) isBlock(e2) else isBlock(e1);
272272
case EBinop(_,_,e): isBlock(e);
273273
case EUnop(_,prefix,e): !prefix && isBlock(e);
@@ -614,6 +614,27 @@ class Parser {
614614
}
615615

616616
mk(EVar(ident,t,e),p1,(e == null) ? tokenMax : pmax(e));
617+
case "final":
618+
var ident = getIdent();
619+
var tk = token();
620+
var t = null;
621+
if( tk == TDoubleDot && allowTypes ) {
622+
t = parseType();
623+
tk = token();
624+
}
625+
var e = null;
626+
627+
switch (tk)
628+
{
629+
case TOp("="): e = parseExpr();
630+
case TOp(_): unexpected(tk);
631+
case TComma | TSemicolon: push(tk);
632+
// Above case should be enough but semicolon is not mandatory after }
633+
case _ if (t != null): push(tk);
634+
default: unexpected(tk);
635+
}
636+
637+
mk(EFinal(ident,t,e),p1,(e == null) ? tokenMax : pmax(e));
617638
case "while":
618639
var econd = parseExpr();
619640
var e = parseExpr();
@@ -1225,7 +1246,7 @@ class Parser {
12251246
ret : inf.ret,
12261247
}),
12271248
};
1228-
case "var":
1249+
case "var" | "final":
12291250
var name = getIdent();
12301251
var get = null, set = null;
12311252
if( maybe(TPOpen) ) {
@@ -1256,6 +1277,7 @@ class Parser {
12561277
set : set,
12571278
type : type,
12581279
expr : expr,
1280+
isfinal : (id == "final")
12591281
}),
12601282
};
12611283
default:

hscript/Printer.hx

+7
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ class Printer {
129129
add(" = ");
130130
expr(e);
131131
}
132+
case EFinal(n, t, e):
133+
add("final " + n);
134+
addType(t);
135+
if( e != null ) {
136+
add(" = ");
137+
expr(e);
138+
}
132139
case EParent(e):
133140
add("("); expr(e); add(")");
134141
case EBlock(el):

hscript/Tools.hx

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Tools {
2727
public static function iter( e : Expr, f : Expr -> Void ) {
2828
switch( expr(e) ) {
2929
case EConst(_), EIdent(_):
30-
case EVar(_, _, e): if( e != null ) f(e);
30+
case EVar(_, _, e) | EFinal(_, _, e): if( e != null ) f(e);
3131
case EParent(e): f(e);
3232
case EBlock(el): for( e in el ) f(e);
3333
case EField(e, _): f(e);
@@ -64,6 +64,7 @@ class Tools {
6464
var edef = switch( expr(e) ) {
6565
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
6666
case EVar(n, t, e): EVar(n, t, if( e != null ) f(e) else null);
67+
case EFinal(n, t, e): EFinal(n, t, if( e != null ) f(e) else null);
6768
case EParent(e): EParent(f(e));
6869
case EBlock(el): EBlock([for( e in el ) f(e)]);
6970
case EField(e, fi): EField(f(e),fi);

0 commit comments

Comments
 (0)