Browse Source

v_flags (#9538)

* start on v_flags

* remove v_captured
Simon Krajewski 5 years ago
parent
commit
a3a4beb9a1

+ 4 - 4
src/codegen/gencommon/closuresToClass.ml

@@ -119,11 +119,11 @@ let mk_conversion_fun gen e =
 	in
 	let block, local = match e.eexpr with
 		| TLocal v ->
-			v.v_capture <- true;
+			add_var_flag v VCaptured;
 			[],e
 		| _ ->
 			let tmp = mk_temp "delegate_conv" e.etype in
-			tmp.v_capture <- true;
+			add_var_flag tmp VCaptured;
 			[{ eexpr = TVar(tmp,Some e); etype = gen.gcon.basic.tvoid; epos = e.epos }], mk_local tmp e.epos
 	in
 	let body = {
@@ -341,7 +341,7 @@ let get_captured expr =
 				ignore(Option.map traverse opt)
 			| TLocal { v_extra = Some( (_ :: _ ),_) } ->
 				()
-			| TLocal(( { v_capture = true } ) as v) ->
+			| TLocal v when has_var_flag v VCaptured ->
 				(if not (Hashtbl.mem ignored v.v_id || Hashtbl.mem ret v.v_id) then begin check_params v.v_type; Hashtbl.replace ret v.v_id expr end);
 			| _ -> Type.iter traverse expr
 	in traverse expr;
@@ -454,7 +454,7 @@ let configure gen ft =
 		(* change all captured variables to this.capturedVariable *)
 		let rec change_captured e =
 			match e.eexpr with
-				| TLocal( ({ v_capture = true }) as v ) when Hashtbl.mem captured_ht v.v_id ->
+				| TLocal v when has_var_flag v VCaptured && Hashtbl.mem captured_ht v.v_id ->
 					mk_this v e.epos
 				| _ -> Type.map_expr change_captured e
 		in

+ 1 - 1
src/codegen/gencommon/initFunction.ml

@@ -49,7 +49,7 @@ let ensure_simple_expr com e =
 
 let handle_override_dynfun acc e this field =
 	let v = mk_temp ("super_" ^ field) e.etype in
-	v.v_capture <- true;
+	add_var_flag v  VCaptured;
 
 	let add_expr = ref None in
 

+ 2 - 2
src/codegen/gencommon/overloadingConstructor.ml

@@ -125,7 +125,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
 			| _ -> ())
 		| _ -> ()) ctor_types;
 		let me = alloc_var "__hx_this" (TInst(cl, List.map snd ctor_types)) in
-		me.v_capture <- true;
+		add_var_flag me VCaptured;
 
 		let fn_args, _ = get_fun ctor.cf_type in
 		let ctor_params = List.map snd ctor_types in
@@ -140,7 +140,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
 		let local_map = Hashtbl.create (List.length cur_tf_args) in
 		let static_tf_args = (me, None) :: List.map (fun (v,b) ->
 			let new_v = alloc_var v.v_name (apply_params cl.cl_params ctor_params v.v_type) in
-			new_v.v_capture <- v.v_capture;
+			add_var_flag new_v VCaptured;
 			Hashtbl.add local_map v.v_id new_v;
 			(new_v, b)
 		) cur_tf_args in

+ 2 - 2
src/core/json/genjson.ml

@@ -295,11 +295,11 @@ and generate_tvar ctx v =
 		"id",jint v.v_id;
 		"name",jstring v.v_name;
 		"type",generate_type ctx v.v_type;
-		"capture",jbool v.v_capture;
+		"capture",jbool (has_var_flag v VCaptured);
 		"extra",jopt generate_extra v.v_extra;
 		"meta",generate_metadata ctx v.v_meta;
 		"pos",generate_pos ctx v.v_pos;
-		"isFinal",jbool v.v_final;
+		"isFinal",jbool (has_var_flag v VFinal);
 		"isInline",jbool (match v.v_extra with Some (_,Some _) -> true | _ -> false);
 	] in
 	let origin_to_int = function

+ 14 - 3
src/core/tFunctions.ml

@@ -31,6 +31,18 @@ let remove_class_field_flag cf (flag : flag_tclass_field) =
 let has_class_field_flag cf (flag : flag_tclass_field) =
 	has_flag cf.cf_flags (int_of_class_field_flag flag)
 
+let int_of_var_flag (flag : flag_tvar) =
+	Obj.magic flag
+
+let add_var_flag v (flag : flag_tvar) =
+	v.v_flags <- set_flag v.v_flags (int_of_var_flag flag)
+
+let remove_var_flag v (flag : flag_tvar) =
+	v.v_flags <- unset_flag v.v_flags (int_of_var_flag flag)
+
+let has_var_flag v (flag : flag_tvar) =
+	has_flag v.v_flags (int_of_var_flag flag)
+
 (* ======= General utility ======= *)
 
 let alloc_var =
@@ -42,11 +54,10 @@ let alloc_var =
 			v_name = n;
 			v_type = t;
 			v_id = !uid;
-			v_capture = false;
-			v_final = (match kind with VUser TVOLocalFunction -> true | _ -> false);
 			v_extra = None;
 			v_meta = [];
-			v_pos = p
+			v_pos = p;
+			v_flags = (match kind with VUser TVOLocalFunction -> int_of_var_flag VFinal | _ -> 0);
 		}
 	)
 

+ 1 - 1
src/core/tOther.ml

@@ -103,7 +103,7 @@ module TExprToExpr = struct
 			let arg (v,c) = (v.v_name,v.v_pos), false, v.v_meta, mk_type_hint v.v_type null_pos, (match c with None -> None | Some c -> Some (convert_expr c)) in
 			EFunction (FKAnonymous,{ f_params = []; f_args = List.map arg f.tf_args; f_type = mk_type_hint f.tf_type null_pos; f_expr = Some (convert_expr f.tf_expr) })
 		| TVar (v,eo) ->
-			EVars ([(v.v_name,v.v_pos), v.v_final, mk_type_hint v.v_type v.v_pos, eopt eo])
+			EVars ([(v.v_name,v.v_pos), has_var_flag v VFinal, mk_type_hint v.v_type v.v_pos, eopt eo])
 		| TBlock el -> EBlock (List.map convert_expr el)
 		| TFor (v,it,e) ->
 			let ein = (EBinop (OpIn,(EConst (Ident v.v_name),it.epos),convert_expr it),it.epos) in

+ 2 - 2
src/core/tPrinting.ml

@@ -174,7 +174,7 @@ let rec s_expr s_type e =
 	let sprintf = Printf.sprintf in
 	let slist f l = String.concat "," (List.map f l) in
 	let loop = s_expr s_type in
-	let s_var v = v.v_name ^ ":" ^ string_of_int v.v_id ^ if v.v_capture then "[c]" else "" in
+	let s_var v = v.v_name ^ ":" ^ string_of_int v.v_id ^ if has_var_flag v VCaptured then "[c]" else "" in
 	let str = (match e.eexpr with
 	| TConst c ->
 		"Const " ^ s_const c
@@ -590,7 +590,7 @@ module Printer = struct
 			"v_id",string_of_int v.v_id;
 			"v_name",v.v_name;
 			"v_type",s_type v.v_type;
-			"v_capture",string_of_bool v.v_capture;
+			"v_capture",string_of_bool (has_var_flag v VCaptured);
 			"v_extra",s_opt s_tvar_extra v.v_extra;
 			"v_meta",s_metadata v.v_meta;
 			"v_pos",s_pos v.v_pos;

+ 6 - 3
src/core/tType.ml

@@ -89,10 +89,9 @@ and tvar = {
 	mutable v_name : string;
 	mutable v_type : t;
 	mutable v_kind : tvar_kind;
-	mutable v_capture : bool;
-	mutable v_final : bool;
 	mutable v_extra : tvar_extra;
 	mutable v_meta : metadata;
+	mutable v_flags : int;
 	v_pos : pos;
 }
 
@@ -372,4 +371,8 @@ type flag_tclass_field =
 	| CfExtern (* This is only set if the field itself is extern, not just the class. *)
 	| CfFinal
 	| CfModifiesThis (* This is set for methods which reassign `this`. E.g. `this = value` *)
-	| CfOverride
+	| CfOverride
+
+type flag_tvar =
+	| VCaptured
+	| VFinal

+ 3 - 3
src/core/texpr.ml

@@ -593,7 +593,7 @@ let rec type_constant_value basic (e,p) =
 	| _ ->
 		error "Constant value expected" p
 
-let is_constant_value basic e = 
+let is_constant_value basic e =
 	try (ignore (type_constant_value basic e); true) with Error (Custom _,_) -> false
 
 let for_remap basic v e1 e2 p =
@@ -769,8 +769,8 @@ let collect_captured_vars e =
 	let accesses_this = ref false in
 	let declare v = Hashtbl.add known v.v_id () in
 	let rec loop e = match e.eexpr with
-		| TLocal ({v_capture = true; v_id = id} as v) when not (Hashtbl.mem known id) ->
-			Hashtbl.add known id ();
+		| TLocal v when has_var_flag v VCaptured &&  not (Hashtbl.mem known v.v_id) ->
+			Hashtbl.add known v.v_id ();
 			unknown := v :: !unknown
 		| TConst (TThis | TSuper) ->
 			accesses_this := true;

+ 3 - 3
src/filters/capturedVars.ml

@@ -163,7 +163,7 @@ let captured_vars com e =
 					| TLocal v ->
 						begin try
 							let v' = List.assoc v.v_id new_vars in
-							v'.v_capture <- true;
+							add_var_flag v' VCaptured;
 							{e with eexpr = TLocal v'}
 						with Not_found ->
 							e
@@ -192,7 +192,7 @@ let captured_vars com e =
 			let used = PMap.map (fun v ->
 				let vt = v.v_type in
 				v.v_type <- impl#captured_type vt;
-				v.v_capture <- true;
+				add_var_flag v VCaptured;
 				vt
 			) used in
 			wrap used e
@@ -280,7 +280,7 @@ let captured_vars com e =
 		local_usage collect_vars e;
 
 		(* mark all capture variables - also used in rename_local_vars at later stage *)
-		PMap.iter (fun _ v -> v.v_capture <- true) !used;
+		PMap.iter (fun _ v -> add_var_flag v VCaptured) !used;
 
 		!assigned
 	in

+ 1 - 1
src/filters/filters.ml

@@ -243,7 +243,7 @@ let check_unification ctx e t =
 	begin match e.eexpr,t with
 		| TLocal v,TType({t_path = ["cs"],("Ref" | "Out")},_) ->
 			(* TODO: this smells of hack, but we have to deal with it somehow *)
-			v.v_capture <- true
+			add_var_flag v VCaptured;
 		| _ ->
 			()
 	end;

+ 1 - 1
src/filters/renameVars.ml

@@ -290,7 +290,7 @@ let maybe_rename_var rc reserved (v,overlaps) =
 		name := v.v_name ^ (string_of_int !count);
 	done;
 	v.v_name <- !name;
-	if rc.rc_no_shadowing || (v.v_capture && rc.rc_hoisting) then reserve reserved v.v_name
+	if rc.rc_no_shadowing || (has_var_flag v VCaptured && rc.rc_hoisting) then reserve reserved v.v_name
 
 (**
 	Rename variables found in `scope`

+ 2 - 2
src/generators/gencpp.ml

@@ -2457,7 +2457,7 @@ let retype_expression ctx request_type function_args function_type expression_tr
             end else begin
                (*print_endline ("Missing tvar " ^ tvar.v_name);*)
                Hashtbl.replace !undeclared name tvar;
-               if tvar.v_capture then
+               if has_var_flag tvar VCaptured then
                   CppVar(VarClosure(tvar)), cpp_type_of tvar.v_type
                else
                   CppExtern(name,false), cpp_type_of tvar.v_type
@@ -7423,7 +7423,7 @@ class script_writer ctx filename asciiOut =
    method writeVar v =
       this#ident v.v_name;
       this#wint v.v_id;
-      this#writeBool v.v_capture;
+      this#writeBool (has_var_flag v VCaptured);
       this#writeType v.v_type;
    method writeList prefix len = this#write (prefix ^" "  ^ (string_of_int (len)) ^ "\n");
    method wpos p = if debug then

+ 3 - 3
src/generators/genhl.ml

@@ -966,7 +966,7 @@ let common_type ctx e1 e2 for_eq p =
 	loop t1 t2
 
 let captured_index ctx v =
-	if not v.v_capture then None else try Some (PMap.find v.v_id ctx.m.mcaptured.c_map) with Not_found -> None
+	if not (has_var_flag v VCaptured) then None else try Some (PMap.find v.v_id ctx.m.mcaptured.c_map) with Not_found -> None
 
 let real_name v =
 	let rec loop = function
@@ -3040,10 +3040,10 @@ and build_capture_vars ctx f =
 	let used_vars = ref PMap.empty in
 	(* get all captured vars in scope, ignore vars that are declared *)
 	let decl_var v =
-		if v.v_capture then ignored_vars := PMap.add v.v_id () !ignored_vars
+		if has_var_flag v VCaptured then ignored_vars := PMap.add v.v_id () !ignored_vars
 	in
 	let use_var v =
-		if v.v_capture then used_vars := PMap.add v.v_id v !used_vars
+		if has_var_flag v VCaptured then used_vars := PMap.add v.v_id v !used_vars
 	in
 	let rec loop e =
 		(match e.eexpr with

+ 6 - 6
src/generators/genneko.ml

@@ -222,7 +222,7 @@ and gen_expr ctx e =
 	| TIdent s when s.[0] = '$' ->
 		(EConst (Builtin (String.sub s 1 (String.length s - 1))),p)
 	| TLocal v ->
-		if v.v_capture then
+		if has_var_flag v VCaptured then
 			(EArray (ident p v.v_name,int p 0),p)
 		else
 			ident p v.v_name
@@ -274,13 +274,13 @@ and gen_expr ctx e =
 		(EVars (
 			let e = (match eo with
 				| None ->
-					if v.v_capture then
+					if has_var_flag v VCaptured then
 						Some (call p (builtin p "array") [null p])
 					else
 						None
 				| Some e ->
 					let e = gen_expr ctx e in
-					if v.v_capture then
+					if has_var_flag v VCaptured then
 						Some (call p (builtin p "array") [e])
 					else
 						Some e
@@ -289,7 +289,7 @@ and gen_expr ctx e =
 		),p)
 	| TFunction f ->
 		let inits = List.fold_left (fun acc (a,c) ->
-			let acc = if a.v_capture then
+			let acc = if has_var_flag a VCaptured then
 				(EBinop ("=",ident p a.v_name,call p (builtin p "array") [ident p a.v_name]),p) :: acc
 			else
 				acc
@@ -307,7 +307,7 @@ and gen_expr ctx e =
 		let it = gen_expr ctx it in
 		let e = gen_expr ctx e in
 		let next = call p (field p (ident p "@tmp") "next") [] in
-		let next = (if v.v_capture then call p (builtin p "array") [next] else next) in
+		let next = (if has_var_flag v VCaptured then call p (builtin p "array") [next] else next) in
 		(EBlock
 			[(EVars ["@tmp", Some it],p);
 			(EWhile (call p (field p (ident p "@tmp") "hasNext") [],
@@ -341,7 +341,7 @@ and gen_expr ctx e =
 					| Some path -> call p (field p (gen_type_path p (["neko"],"Boot")) "__instanceof") [ident p "@tmp"; gen_type_path p path]
 				) in
 				let id = ident p "@tmp" in
-				let id = (if v.v_capture then call p (builtin p "array") [id] else id) in
+				let id = (if has_var_flag v VCaptured then call p (builtin p "array") [id] else id) in
 				let e = gen_expr ctx e in
 				(EIf (cond,(EBlock [
 					EVars [v.v_name,Some id],p;

+ 1 - 1
src/generators/genswf9.ml

@@ -502,7 +502,7 @@ let rename_block_var ctx v =
 let define_local ctx ?(init=false) v p =
 	let name = v.v_name in
 	let t = v.v_type in
-	let l = (if v.v_capture then begin
+	let l = (if has_var_flag v VCaptured then begin
 			let topt = type_opt ctx t in
 			if List.exists (fun (_,x,_) -> name = x) ctx.block_vars || is_member ctx name then rename_block_var ctx v;
 			let pos = List.length ctx.block_vars + 1 in

+ 4 - 4
src/macro/eval/evalJit.ml

@@ -62,7 +62,7 @@ open EvalJitContext
 let rec op_assign ctx jit e1 e2 = match e1.eexpr with
 	| TLocal var ->
 		let exec = jit_expr jit false e2 in
-		if var.v_capture then emit_capture_write (get_capture_slot jit var) exec
+		if has_var_flag var VCaptured then emit_capture_write (get_capture_slot jit var) exec
 		else emit_local_write (get_slot jit var.v_id e1.epos) exec
 	| TField(ef,fa) ->
 		let name = hash (field_name fa) in
@@ -111,7 +111,7 @@ let rec op_assign ctx jit e1 e2 = match e1.eexpr with
 and op_assign_op jit op e1 e2 prefix = match e1.eexpr with
 	| TLocal var ->
 		let exec = jit_expr jit false e2 in
-		if var.v_capture then emit_capture_read_write (get_capture_slot jit var) exec op prefix
+		if has_var_flag var VCaptured then emit_capture_read_write (get_capture_slot jit var) exec op prefix
 		else emit_local_read_write (get_slot jit var.v_id e1.epos) exec op prefix
 	| TField(ef,fa) ->
 		let name = hash (field_name fa) in
@@ -163,7 +163,7 @@ and unop jit op flag e1 p =
 		emit_op_sub p (fun _ -> vint32 (Int32.minus_one)) exec
 	| Increment ->
 		begin match Texpr.skip e1 with
-		| {eexpr = TLocal v} when not v.v_capture ->
+		| {eexpr = TLocal v} when not (has_var_flag v VCaptured) ->
 			let slot = get_slot jit v.v_id e1.epos in
 			if flag = Prefix then emit_local_incr_prefix slot e1.epos
 			else emit_local_incr_postfix slot e1.epos
@@ -522,7 +522,7 @@ and jit_expr jit return e =
 		end
 	(* read *)
 	| TLocal var ->
-		if var.v_capture then emit_capture_read (get_capture_slot jit var)
+		if has_var_flag var VCaptured then emit_capture_read (get_capture_slot jit var)
 		else emit_local_read (get_slot jit var.v_id e.epos)
 	| TField(e1,fa) ->
 		let name = hash (field_name fa) in

+ 2 - 2
src/macro/eval/evalJitContext.ml

@@ -111,7 +111,7 @@ let add_local jit var = match jit.scopes with
 	Returns either [Env slot] if the variable is captured or [Local slot] otherwise.
 *)
 let declare_local jit var =
-	if var.v_capture then Env (add_capture jit var true)
+	if has_var_flag var VCaptured then Env (add_capture jit var true)
 	else Local (add_local jit var)
 
 (*
@@ -122,7 +122,7 @@ let declare_local jit var =
 *)
 let declare_arg jit var =
 	let varacc = add_local jit var in
-	if var.v_capture then add_capture jit var true,Some varacc else varacc,None
+	if has_var_flag var VCaptured then add_capture jit var true,Some varacc else varacc,None
 
 (* Declares a variable for `this` in context [jit]. *)
 let declare_local_this jit = match jit.scopes with

+ 1 - 1
src/macro/macroApi.ml

@@ -1152,7 +1152,7 @@ and encode_tvar v =
 		"id", vint v.v_id;
 		"name", encode_string v.v_name;
 		"t", encode_type v.v_type;
-		"capture", vbool v.v_capture;
+		"capture", vbool (has_var_flag v VCaptured);
 		"extra", vopt f_extra v.v_extra;
 		"meta", encode_meta v.v_meta (fun m -> v.v_meta <- m);
 		"$", encode_unsafe (Obj.repr v);

+ 6 - 6
src/optimization/analyzer.ml

@@ -145,7 +145,7 @@ module Ssa = struct
 			let v' = alloc_var v.v_kind v.v_name v.v_type v.v_pos in
 			declare_var ctx.graph v' bb;
 			v'.v_meta <- v.v_meta;
-			v'.v_capture <- v.v_capture;
+			if has_var_flag v VCaptured then add_var_flag v' VCaptured;
 			add_var_def ctx.graph bb v';
 			set_reaching_def ctx.graph v' (get_reaching_def ctx.graph v);
 			set_reaching_def ctx.graph v (Some v');
@@ -394,7 +394,7 @@ module ConstPropagation = DataFlow(struct
 			| TTypeExpr mt ->
 				ModuleType(mt,e.etype)
 			| TLocal v ->
-				if (follow v.v_type) == t_dynamic || v.v_capture then
+				if (follow v.v_type) == t_dynamic || has_var_flag v VCaptured then
 					Bottom
 				else
 					get_cell v.v_id
@@ -486,7 +486,7 @@ module ConstPropagation = DataFlow(struct
 				if not (type_change_ok ctx.com t e.etype) then raise Not_found;
 				mk (TTypeExpr mt) t e.epos
 		in
-		let is_special_var v = v.v_capture || ExtType.has_variable_semantics v.v_type in
+		let is_special_var v = has_var_flag v VCaptured || ExtType.has_variable_semantics v.v_type in
 		let rec commit e = match e.eexpr with
 			| TLocal v when not (is_special_var v) ->
 				begin try
@@ -554,7 +554,7 @@ module CopyPropagation = DataFlow(struct
 
 	let transfer ctx bb e =
 		let rec loop e = match e.eexpr with
-			| TLocal v when not v.v_capture ->
+			| TLocal v when not (has_var_flag v VCaptured) ->
 				Local v
 			| TConst TThis ->
 				This e.etype
@@ -570,7 +570,7 @@ module CopyPropagation = DataFlow(struct
 
 	let commit ctx =
 		let rec commit bb e = match e.eexpr with
-			| TLocal v when not v.v_capture ->
+			| TLocal v when not (has_var_flag v VCaptured) ->
 				begin try
 					let lat = get_cell v.v_id in
 					let leave () =
@@ -652,7 +652,7 @@ module LocalDce = struct
 			Meta.has Meta.Used v.v_meta
 		in
 		let keep v =
-			is_used v || ((match v.v_kind with VUser _ | VInlined -> true | _ -> false) && not ctx.config.local_dce) || ExtType.has_reference_semantics v.v_type || v.v_capture || Meta.has Meta.This v.v_meta
+			is_used v || ((match v.v_kind with VUser _ | VInlined -> true | _ -> false) && not ctx.config.local_dce) || ExtType.has_reference_semantics v.v_type || has_var_flag v VCaptured || Meta.has Meta.This v.v_meta
 		in
 		let rec use v =
 			if not (is_used v) then begin

+ 5 - 5
src/optimization/analyzerTexpr.ml

@@ -311,15 +311,15 @@ module InterferenceReport = struct
 			(* vars *)
 			| TLocal v ->
 				set_var_read ir v;
-				if v.v_capture then set_state_read ir;
+				if has_var_flag v VCaptured then set_state_read ir;
 			| TBinop(OpAssign,{eexpr = TLocal v},e2) ->
 				set_var_write ir v;
-				if v.v_capture then set_state_write ir;
+				if has_var_flag v VCaptured then set_state_write ir;
 				loop e2
 			| TBinop(OpAssignOp _,{eexpr = TLocal v},e2) ->
 				set_var_read ir v;
 				set_var_write ir v;
-				if v.v_capture then begin
+				if has_var_flag v VCaptured then begin
 					set_state_read ir;
 					set_state_write ir;
 				end;
@@ -651,7 +651,7 @@ module Fusion = struct
 				end
 			| {eexpr = TVar(v1,Some e1)} :: el when config.optimize && config.local_dce && state#get_reads v1 = 0 && state#get_writes v1 = 0 ->
 				fuse acc (e1 :: el)
-			| ({eexpr = TVar(v1,None)} as ev) :: el when not v1.v_capture ->
+			| ({eexpr = TVar(v1,None)} as ev) :: el when not (has_var_flag v1 VCaptured) ->
 				let found = ref false in
 				let rec replace deep e = match e.eexpr with
 					| TBinop(OpAssign,{eexpr = TLocal v2},e2) when v1 == v2 ->
@@ -748,7 +748,7 @@ module Fusion = struct
 							found := true;
 							if type_change_ok com v1.v_type e1.etype then e1 else mk (TCast(e1,None)) v1.v_type e.epos
 						| TLocal v ->
-							if has_var_write ir v || ((v.v_capture || ExtType.has_reference_semantics v.v_type) && (has_state_write ir)) then raise Exit;
+							if has_var_write ir v || ((has_var_flag v VCaptured || ExtType.has_reference_semantics v.v_type) && (has_state_write ir)) then raise Exit;
 							e
 						| TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) ->
 							let e2 = replace e2 in

+ 3 - 3
src/optimization/analyzerTexprTransformer.ml

@@ -83,7 +83,7 @@ let rec func ctx bb tf t p =
 	in
 	let check_unbound_call s el =
 		if s = "$ref" then begin match el with
-			| [{eexpr = TLocal v}] -> v.v_capture <- true
+			| [{eexpr = TLocal v}] -> add_var_flag v VCaptured
 			| _ -> ()
 		end;
 		if is_unbound_call_that_might_have_side_effects s el then ctx.has_unbound <- true;
@@ -304,7 +304,7 @@ let rec func ctx bb tf t p =
 		let bb = ref bb in
 		let check e t = match e.eexpr with
 			| TLocal v when ExtType.has_reference_semantics t ->
-				v.v_capture <- true;
+				add_var_flag v VCaptured;
 				e
 			| _ ->
 				if ExtType.has_variable_semantics t then begin
@@ -733,7 +733,7 @@ and func ctx i =
 					false
 			in
 			begin match e1.eexpr,e2.eexpr with
-				| TLocal v1,TLocal v2 when v1 == v2 && not v1.v_capture && is_valid_assign_op op ->
+				| TLocal v1,TLocal v2 when v1 == v2 && not (has_var_flag v1 VCaptured) && is_valid_assign_op op ->
 					begin match op,e3.eexpr with
 						| (OpAdd|OpSub) as op,TConst (TInt i32) when Int32.to_int i32 = 1 && ExtType.is_numeric (Abstract.follow_with_abstracts v1.v_type) ->
 							let op = match op with

+ 1 - 1
src/optimization/optimizerTexpr.ml

@@ -52,7 +52,7 @@ let create_affection_checker () =
 	let rec might_be_affected e =
 		let rec loop e = match e.eexpr with
 			| TConst _ | TFunction _ | TTypeExpr _ -> ()
-			| TLocal {v_capture = true} -> raise Exit
+			| TLocal v when has_var_flag v VCaptured -> raise Exit
 			| TLocal v when Hashtbl.mem modified_locals v.v_id -> raise Exit
 			| TField(e1,fa) when not (is_read_only_field_access e1 fa) -> raise Exit
 			| TCall _ | TNew _ -> raise Exit

+ 1 - 1
src/typing/matcher.ml

@@ -203,7 +203,7 @@ module Pattern = struct
 				v
 			| _ ->
 				let v = alloc_var (VUser TVOPatternVariable) name t p in
-				if final then v.v_final <- true;
+				if final then add_var_flag v VFinal;
 				pctx.current_locals <- PMap.add name (v,p) pctx.current_locals;
 				ctx.locals <- PMap.add name v ctx.locals;
 				v

+ 2 - 2
src/typing/typer.ml

@@ -35,7 +35,7 @@ open Calls
 
 let check_assign ctx e =
 	match e.eexpr with
-	| TLocal {v_final = true} ->
+	| TLocal v when has_var_flag v VFinal ->
 		error "Cannot assign to final" e.epos
 	| TLocal {v_extra = None} | TArray _ | TField _ | TIdent _ ->
 		()
@@ -1448,7 +1448,7 @@ and type_vars ctx vl p =
 					Some e
 			) in
 			let v = add_local_with_origin ctx TVOLocalVariable v t pv in
-			if final then v.v_final <- true;
+			if final then add_var_flag v VFinal;
 			if ctx.in_display && DisplayPosition.display_position#enclosed_in pv then
 				DisplayEmitter.display_variable ctx v pv;
 			v,e