<commit_before>(*
 *  Haxe Compiler
 *  Copyright (c)2005 <NAME>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)
open Swf
open Ast
open Type

type context = {
	(* code *)
	opcodes : actions;
	mutable code_pos : int;
	mutable stack_size : int;
	mutable opt_push : bool;
	mutable ident_count : int;

	(* management *)
	packages : (string list,unit) Hashtbl.t;
	idents : (string * bool,int) Hashtbl.t;	
	mutable movieclips : module_path list;
	mutable inits : texpr list;
	mutable statics : (tclass * bool * string * texpr) list;
	mutable regs : (string,int option) PMap.t;
	mutable reg_count : int;
	mutable reg_max : int;
	mutable fun_stack : int;
	version : int;
	mutable curclass : (string list * string);
	mutable curmethod : string;
	mutable fun_pargs : (int * bool list) list;

	(* loops *)
	mutable cur_block : texpr list;
	mutable breaks : (unit -> unit) list;
	mutable continues : (int -> unit) list;
	mutable loop_stack : int;
}

let error p = Typer.error "Invalid expression" p
let stack_error p = Typer.error "Stack error" p
let protect_all = ref true
let extern_boot = ref false

(* -------------------------------------------------------------- *)
(* Bytecode Helpers *)

type kind =
	| VarReg of int
	| VarStr
	| VarObj
	| VarClosure

type push_style =
	| VStr of string * bool
	| VInt of int
	| VInt32 of int32
	| VFloat of float
	| VReg of int
	| VThis
	| VNull
	| VSuper

let stack_delta = function
	| APush l -> List.length l
	| ASetReg _ -> 0
	| AAdd | ADivide | ASubtract | AMultiply | AMod | AStringAdd -> -1
	| AAnd | AOr | AXor | AShl | AShr | AAsr -> -1
	| ACompare | AGreater -> -1
	| AEval | ANot | AJump _ | AToInt | AToNumber | AToString | ATry _ | ASwap -> 0
	| ACondJump _ -> -1
	| AEqual | APhysEqual -> -1
	| ANew -> -1 (** only if 0 params **)
	| AObject | AInitArray -> 0 (** calculated outside **)
	| ASet -> -2
	| APop -> -1
	| AFunction _ | AFunction2 _ -> 1
	| ADup -> 1
	| AWith _ -> -1
	| AObjGet -> -1
	| AObjSet -> -3
	| ALocalVar -> -1
	| ALocalAssign -> -2
	| AReturn -> -1
	| AGetURL2 _ -> -2
	| ADeleteObj | AInstanceOf | ACast -> -1
	| AExtends | AImplements -> -2
	| AEnum2 | ATrace | AThrow -> -1
	| AGetTimer -> 1
	| AIncrement | ADecrement | AChr | AOrd | ARandom | ADelete | ATypeOf | ATargetPath -> 0
	| AObjCall | ACall | ANewMethod -> assert false
	| AStringPool _ -> 0
	| op -> failwith ("Unknown stack delta for " ^ (ActionScript.action_string (fun _ -> "") 0 op))

let overflow ctx =
	failwith ("In or near the method " ^ s_type_path ctx.curclass ^ "." ^ ctx.curmethod ^
	" too much code is causing an overflow that can't be handled by the SWF format. " ^
	"Please split your code in several methods so it can be correctly compiled.")

let write ctx op =
	let write b op =
		DynArray.add ctx.opcodes op;
		ctx.code_pos <- ctx.code_pos + 1;
		ctx.stack_size <- ctx.stack_size + stack_delta op;
		ctx.opt_push <- b
	in
	match op with
	| APush l when ctx.opt_push ->
		(match DynArray.last ctx.opcodes with
		| (APush l2) as a ->
			ctx.code_pos <- ctx.code_pos - 1;
			ctx.stack_size <- ctx.stack_size - stack_delta a;
			DynArray.delete_last ctx.opcodes;
			write true (APush (l2 @ l))
		| _ ->
			assert false)
	| APush _ ->
		write true op
	| _ ->
		write false op

let call ctx kind n =
	let op , n = (match kind with
		| VarReg r ->
			write ctx (APush [PReg r;PUndefined]);
			AObjCall , n + 2
		| VarStr ->
			ACall , n + 1
		| VarClosure | VarObj ->
			AObjCall , n + 2
	) in
	DynArray.add ctx.opcodes op;
	ctx.opt_push <- false;
	ctx.code_pos <- ctx.code_pos + 1;
	ctx.stack_size <- ctx.stack_size - n

let new_call ctx kind n  =
	let op , n = (match kind with
		| VarReg r ->
			write ctx (APush [PReg r;PUndefined]);
			ANewMethod , n + 2
		| VarStr ->
			ANew , n + 1
		| VarClosure | VarObj ->
			ANewMethod , n + 2
	) in
	DynArray.add ctx.opcodes op;
	ctx.opt_push <- false;
	ctx.code_pos <- ctx.code_pos + 1;
	ctx.stack_size <- ctx.stack_size - n

let always_protected = function
	| "prototype" | "toString" | "__resolve" | "__constructor__" | "__proto__" -> true
	(*// haxe.PosInfos *)
	| "fileName" | "lineNumber" | "className" | "methodName" | "customParams" -> true
	| s ->
		if String.length s > 1 && s.[0] = '_' && s.[1] != '_' then
			true
		else
			false

let unprotect a = !protect_all || always_protected a

let is_protected_name path ext =
	match path with
	| ["flash"] , "Boot" | ["flash"] , "Lib" -> false
	| "flash" :: _ , _ -> ext
	| [] , "Array" | [] , "Math" | [] , "Date" | [] , "String" -> true
	| _ -> false

let rec is_protected ctx t check_mt =
	match t with
	| TInst (c,_) ->
		let rec loop c =
			is_protected_name c.cl_path c.cl_extern
			|| (check_mt && List.exists (fun (i,_) -> i.cl_path = (["mt"],"Protect")) c.cl_implements)
			|| match c.cl_super with None -> false | Some (c,_) -> loop c
		in
		loop c
	| TMono r ->
		(match !r with
		| None -> true
		| Some t -> is_protected ctx t check_mt)
	| TSign (s,_) ->
		(match s.s_static with
		| None -> is_protected ctx s.s_type check_mt
		| Some c -> is_protected_name c.cl_path c.cl_extern)
	| _ -> false

let push ctx items =
	write ctx (APush (List.map (fun i ->
		match i with
		| VStr (str,flag) ->
			let flag = if flag || unprotect str then true else flag in
			let n = (try
				Hashtbl.find ctx.idents (str,flag)
			with Not_found ->
				let n = ctx.ident_count in
				ctx.ident_count <- n + 1;
				Hashtbl.add ctx.idents (str,flag) n;
				n
			) in
			if n <= 0xFF then
				PStack n
			else
				PStack2 n
		| VInt n -><commit_msg>bugfix in is_prot<commit_after>(*
 *  Haxe Compiler
 *  Copyright (c)2005 <NAME>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)
open Swf
open Ast
open Type

type context = {
	(* code *)
	opcodes : actions;
	mutable code_pos : int;
	mutable stack_size : int;
	mutable opt_push : bool;
	mutable ident_count : int;

	(* management *)
	packages : (string list,unit) Hashtbl.t;
	idents : (string * bool,int) Hashtbl.t;	
	mutable movieclips : module_path list;
	mutable inits : texpr list;
	mutable statics : (tclass * bool * string * texpr) list;
	mutable regs : (string,int option) PMap.t;
	mutable reg_count : int;
	mutable reg_max : int;
	mutable fun_stack : int;
	version : int;
	mutable curclass : (string list * string);
	mutable curmethod : string;
	mutable fun_pargs : (int * bool list) list;

	(* loops *)
	mutable cur_block : texpr list;
	mutable breaks : (unit -> unit) list;
	mutable continues : (int -> unit) list;
	mutable loop_stack : int;
}

let error p = Typer.error "Invalid expression" p
let stack_error p = Typer.error "Stack error" p
let protect_all = ref true
let extern_boot = ref false

(* -------------------------------------------------------------- *)
(* Bytecode Helpers *)

type kind =
	| VarReg of int
	| VarStr
	| VarObj
	| VarClosure

type push_style =
	| VStr of string * bool
	| VInt of int
	| VInt32 of int32
	| VFloat of float
	| VReg of int
	| VThis
	| VNull
	| VSuper

let stack_delta = function
	| APush l -> List.length l
	| ASetReg _ -> 0
	| AAdd | ADivide | ASubtract | AMultiply | AMod | AStringAdd -> -1
	| AAnd | AOr | AXor | AShl | AShr | AAsr -> -1
	| ACompare | AGreater -> -1
	| AEval | ANot | AJump _ | AToInt | AToNumber | AToString | ATry _ | ASwap -> 0
	| ACondJump _ -> -1
	| AEqual | APhysEqual -> -1
	| ANew -> -1 (** only if 0 params **)
	| AObject | AInitArray -> 0 (** calculated outside **)
	| ASet -> -2
	| APop -> -1
	| AFunction _ | AFunction2 _ -> 1
	| ADup -> 1
	| AWith _ -> -1
	| AObjGet -> -1
	| AObjSet -> -3
	| ALocalVar -> -1
	| ALocalAssign -> -2
	| AReturn -> -1
	| AGetURL2 _ -> -2
	| ADeleteObj | AInstanceOf | ACast -> -1
	| AExtends | AImplements -> -2
	| AEnum2 | ATrace | AThrow -> -1
	| AGetTimer -> 1
	| AIncrement | ADecrement | AChr | AOrd | ARandom | ADelete | ATypeOf | ATargetPath -> 0
	| AObjCall | ACall | ANewMethod -> assert false
	| AStringPool _ -> 0
	| op -> failwith ("Unknown stack delta for " ^ (ActionScript.action_string (fun _ -> "") 0 op))

let overflow ctx =
	failwith ("In or near the method " ^ s_type_path ctx.curclass ^ "." ^ ctx.curmethod ^
	" too much code is causing an overflow that can't be handled by the SWF format. " ^
	"Please split your code in several methods so it can be correctly compiled.")

let write ctx op =
	let write b op =
		DynArray.add ctx.opcodes op;
		ctx.code_pos <- ctx.code_pos + 1;
		ctx.stack_size <- ctx.stack_size + stack_delta op;
		ctx.opt_push <- b
	in
	match op with
	| APush l when ctx.opt_push ->
		(match DynArray.last ctx.opcodes with
		| (APush l2) as a ->
			ctx.code_pos <- ctx.code_pos - 1;
			ctx.stack_size <- ctx.stack_size - stack_delta a;
			DynArray.delete_last ctx.opcodes;
			write true (APush (l2 @ l))
		| _ ->
			assert false)
	| APush _ ->
		write true op
	| _ ->
		write false op

let call ctx kind n =
	let op , n = (match kind with
		| VarReg r ->
			write ctx (APush [PReg r;PUndefined]);
			AObjCall , n + 2
		| VarStr ->
			ACall , n + 1
		| VarClosure | VarObj ->
			AObjCall , n + 2
	) in
	DynArray.add ctx.opcodes op;
	ctx.opt_push <- false;
	ctx.code_pos <- ctx.code_pos + 1;
	ctx.stack_size <- ctx.stack_size - n

let new_call ctx kind n  =
	let op , n = (match kind with
		| VarReg r ->
			write ctx (APush [PReg r;PUndefined]);
			ANewMethod , n + 2
		| VarStr ->
			ANew , n + 1
		| VarClosure | VarObj ->
			ANewMethod , n + 2
	) in
	DynArray.add ctx.opcodes op;
	ctx.opt_push <- false;
	ctx.code_pos <- ctx.code_pos + 1;
	ctx.stack_size <- ctx.stack_size - n

let always_protected = function
	| "prototype" | "toString" | "__resolve" | "__constructor__" | "__proto__" -> true
	(*// haxe.PosInfos *)
	| "fileName" | "lineNumber" | "className" | "methodName" | "customParams" -> true
	| s ->
		if String.length s > 1 && s.[0] = '_' && s.[1] != '_' then
			true
		else
			false

let unprotect a = !protect_all || always_protected a

let is_protected_name path ext =
	match path with
	| ["flash"] , "Boot" | ["flash"] , "Lib" -> false
	| "flash" :: _ , _ -> ext
	| [] , "Array" | [] , "Math" | [] , "Date" | [] , "String" -> true
	| _ -> false

let rec is_protected ctx t check_mt =
	match t with
	| TInst (c,_) ->
		let rec loop c =
			is_protected_name c.cl_path c.cl_extern
			|| (check_mt && List.exists (fun (i,_) -> i.cl_path = (["mt"],"Protect")) c.cl_implements)
			|| match c.cl_super with None -> false | Some (c,_) -> loop c
		in
		loop c
	| TMono r ->
		(match !r with
		| None -> true
		| Some t -> is_protected ctx t check_mt)
	| TLazy f ->
		is_protected ctx ((!f)()) check_mt
	| TSign (s,_) ->
		(match s.s_static with
		| None -> is_protected ctx s.s_type check_mt
		| Some c -> is_protected_name c.cl_path c.cl_extern)
	| _ -> false

let push ctx items =
	write ctx (APush (List.map (fun i ->
		match i with
		| VStr (str,flag) ->
			let flag = if flag || unprotect str then true else flag in
			let n = (try
				Hashtbl.find ctx.idents (str,flag)
			with Not_found ->
				let n = ctx.ident_count in
				ctx.ident_count <- n + 1;
				Hashtbl.add ctx.idents (str,flag) n;
				n
			) in
			if n <= 0xFF then
				PStack n
			else
				PStack2 n
		| VInt n ->
{'fraction_non_alphanumeric': 0.1336022589753933, 'fraction_numerical': 0.011617587736990722, 'mean_word_length': 2.739366515837104, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 138, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2578753', 'n_tokens_mistral': 4800, 'n_tokens_neox': 4514, 'n_words': 1488}