<commit_before>package hxsl;
using hxsl.Ast;

class ShaderInstance {
	public var id : Int;
	public var shader : ShaderData;
	public var params : Map<Int,Int>;
	public function new(shader) {
		id = Tools.allocVarId();
		this.shader = shader;
		params = new Map();
	}
}

class ShaderGlobal {
	public var v : TVar;
	public var globalId : Int;
	public function new(v, gid) {
		this.v = v;
		this.globalId = gid;
	}
}

class ShaderConst {
	public var v : TVar;
	public var pos : Int;
	public var bits : Int;
	public var globalId : Int;
	public var next : ShaderConst;
	public function new(v, pos, bits) {
		this.v = v;
		this.pos = pos;
		this.bits = bits;
	}
}

class SharedShader {

	public var data : ShaderData;
	public var globals : Array<ShaderGlobal>;
	public var consts : ShaderConst;
	var instanceCache : Map<Int,ShaderInstance>;
	var paramsCount : Int;

	public function new(src:String) {
		instanceCache = new Map();
		data = haxe.Unserializer.run(src);
		consts = null;
		globals = [];
		for( v in data.vars )
			browseVar(v);
		if( consts == null ) {
			var hasFun = false;
			for( f in data.funs )
				switch( f.ref.name ) {
				case "vertex", "fragment", "__init__", "__init__vertex", "__init__fragment":
				default: hasFun = true; break;
				}
			if( !hasFun ) {
				var i = new ShaderInstance(data);
				paramsCount = 0;
				for( v in data.vars )
					addSelfParam(i, v);
				instanceCache.set(0, i);
			}
		}
	}

	public inline function getInstance( constBits : Int ) {
		var i = instanceCache.get(constBits);
		return if( i == null ) makeInstance(constBits) else i;
	}

	function makeInstance( constBits : Int )  {
		var eval = new hxsl.Eval();
		var c = consts;
		while( c != null ) {
			eval.setConstant(c.v, switch( c.v.type ) {
			case TBool: CBool((constBits >>> c.pos) & 1 != 0);
			case TInt: CInt((constBits >>> c.pos) & ((1 << c.bits) - 1));
			default: throw "assert";
			});
			c = c.next;
		}
		var i = new ShaderInstance(eval.eval(data));
		#if debug
		Printer.check(i.shader, [data]);
		#end
		paramsCount = 0;
		for( v in data.vars )
			addParam(eval, i, v);
		instanceCache.set(constBits, i);
		return i;
	}

	function addSelfParam( i : ShaderInstance, v : TVar ) {
		switch( v.type ) {
		case TStruct(vl):
			for( v in vl )
				addSelfParam(i, v);
		default:
			if( v.kind == Param ) {
				i.params.set( v.id,  paramsCount );
				paramsCount++;
			}
		}
	}

	function addParam( eval : Eval, i : ShaderInstance, v : TVar ) {
		switch( v.type ) {
		case TStruct(vl):
			for( v in vl )
				addParam(eval, i, v);
		default:
			if( v.kind == Param ) {
				i.params.set( eval.varMap.get(v).id,  paramsCount );
				paramsCount++;
			}
		}
	}

	function browseVar( v : TVar, ?path : String ) {
		v.id = Tools.allocVarId();
		if( path == null )
			path = v.getName();
		else
			path += "." + v.name;
		switch( v.type ) {
		case TStruct(vl):
			for( vs in vl )
				browseVar(vs,path);
		default:
			var globalId = 0;
			if( v.kind == Global ) {
				globalId = Globals.allocID(path);
				globals.push(new ShaderGlobal(v,globalId));
			}
			if( !v.isConst() )
				return;
			var bits = v.getConstBits();
			if( bits > 0 ) {
				var pos = consts == null ? 0 : consts.pos + consts.bits;
				var c = new ShaderConst(v, pos, bits);
				c.globalId = globalId;
				c.next = consts;
				consts = c;
			}
		}
	}

}
<commit_msg>disabled optim if no const (close #113)<commit_after>package hxsl;
using hxsl.Ast;

class ShaderInstance {
	public var id : Int;
	public var shader : ShaderData;
	public var params : Map<Int,Int>;
	public function new(shader) {
		id = Tools.allocVarId();
		this.shader = shader;
		params = new Map();
	}
}

class ShaderGlobal {
	public var v : TVar;
	public var globalId : Int;
	public function new(v, gid) {
		this.v = v;
		this.globalId = gid;
	}
}

class ShaderConst {
	public var v : TVar;
	public var pos : Int;
	public var bits : Int;
	public var globalId : Int;
	public var next : ShaderConst;
	public function new(v, pos, bits) {
		this.v = v;
		this.pos = pos;
		this.bits = bits;
	}
}

class SharedShader {

	public var data : ShaderData;
	public var globals : Array<ShaderGlobal>;
	public var consts : ShaderConst;
	var instanceCache : Map<Int,ShaderInstance>;
	var paramsCount : Int;

	public function new(src:String) {
		instanceCache = new Map();
		data = haxe.Unserializer.run(src);
		consts = null;
		globals = [];
		for( v in data.vars )
			browseVar(v);
		// don't try to optimize if consts is null, we need to do a few things in Eval
	}

	public inline function getInstance( constBits : Int ) {
		var i = instanceCache.get(constBits);
		return if( i == null ) makeInstance(constBits) else i;
	}

	function makeInstance( constBits : Int )  {
		var eval = new hxsl.Eval();
		var c = consts;
		while( c != null ) {
			eval.setConstant(c.v, switch( c.v.type ) {
			case TBool: CBool((constBits >>> c.pos) & 1 != 0);
			case TInt: CInt((constBits >>> c.pos) & ((1 << c.bits) - 1));
			default: throw "assert";
			});
			c = c.next;
		}
		var i = new ShaderInstance(eval.eval(data));
		#if debug
		Printer.check(i.shader, [data]);
		#end
		paramsCount = 0;
		for( v in data.vars )
			addParam(eval, i, v);
		instanceCache.set(constBits, i);
		return i;
	}

	function addSelfParam( i : ShaderInstance, v : TVar ) {
		switch( v.type ) {
		case TStruct(vl):
			for( v in vl )
				addSelfParam(i, v);
		default:
			if( v.kind == Param ) {
				i.params.set( v.id,  paramsCount );
				paramsCount++;
			}
		}
	}

	function addParam( eval : Eval, i : ShaderInstance, v : TVar ) {
		switch( v.type ) {
		case TStruct(vl):
			for( v in vl )
				addParam(eval, i, v);
		default:
			if( v.kind == Param ) {
				i.params.set( eval.varMap.get(v).id,  paramsCount );
				paramsCount++;
			}
		}
	}

	function browseVar( v : TVar, ?path : String ) {
		v.id = Tools.allocVarId();
		if( path == null )
			path = v.getName();
		else
			path += "." + v.name;
		switch( v.type ) {
		case TStruct(vl):
			for( vs in vl )
				browseVar(vs,path);
		default:
			var globalId = 0;
			if( v.kind == Global ) {
				globalId = Globals.allocID(path);
				globals.push(new ShaderGlobal(v,globalId));
			}
			if( !v.isConst() )
				return;
			var bits = v.getConstBits();
			if( bits > 0 ) {
				var pos = consts == null ? 0 : consts.pos + consts.bits;
				var c = new ShaderConst(v, pos, bits);
				c.globalId = globalId;
				c.next = consts;
				consts = c;
			}
		}
	}

}

{'fraction_non_alphanumeric': 0.13913824057450627, 'fraction_numerical': 0.0031418312387791743, 'mean_word_length': 2.419437340153453, 'pattern_counts': {'":': 1, '<': 13, '<?xml version=': 0, '>': 23, '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': '3177244', 'n_tokens_mistral': 2811, 'n_tokens_neox': 2427, 'n_words': 667}