/// <summary> /// Implements applicative-order evaluation. /// </summary> /// <param name="env"></param> /// <returns></returns> public override IValue Evaluate(Environment env) { // Eval and get the operator IValue procedure = ProcedureExpression.Evaluate(env); // Both primitive & compound procedures are strict var arguments = from argExpr in ArgumentExpressions select argExpr.Evaluate(env); switch (procedure) { case PrimitiveProcedure pproc: return(pproc.Execute(arguments.ToList())); case CompoundProcedure cproc: return(cproc.Execute(arguments.ToList())); default: throw new RuntimeErrorException("procedure application", $"Expected a procedure that can be applied. Given: {procedure.Represent()}"); } }
static void ProcedureProcessor(StringBuilder stringBuilder, ProcedureExpression expression, ShaderMetadata metadata) { // SWAP ARGUMENTS !!! if (expression == null) { return; } // Pre process // For procedure "tex2D" if (expression.Name.Equals("tex2D") && metadata is PixelShaderMetadata) { // Cast to pixel metadata var pixelMetadata = metadata as PixelShaderMetadata; // Find tex2D syntax part TextPart tex2DPart = expression.ConstituentSymbols[0] as TextPart; // Find sampler name TextPart samplerPart = expression.ConstituentSymbols[2] as TextPart; // Find sampler expression SamplerExpression samplerExpression = pixelMetadata.Samplers.Find(s => s.Name == samplerPart.TextValue); if (samplerExpression == null) { throw new ArgumentNullException("samplerExpression"); } // Find texture name if (string.IsNullOrEmpty(samplerExpression.Resource)) { throw new ArgumentNullException("samplerExpression.Resource"); } // Modify tex2DPart.TextValue = samplerExpression.Resource + ".Sample"; } if (expression.Name.Equals("texCube") && metadata is PixelShaderMetadata) { // Cast to pixel metadata var pixelMetadata = metadata as PixelShaderMetadata; // Find tex2D syntax part TextPart texCubePart = expression.ConstituentSymbols[0] as TextPart; // Find sampler name TextPart samplerPart = expression.ConstituentSymbols[2] as TextPart; // Find sampler expression SamplerExpression samplerExpression = pixelMetadata.Samplers.Find(s => s.Name == samplerPart.TextValue); if (samplerExpression == null) { throw new ArgumentNullException("samplerExpression"); } // Find texture name if (string.IsNullOrEmpty(samplerExpression.Resource)) { throw new ArgumentNullException("samplerExpression.Resource"); } // Modify texCubePart.TextValue = samplerExpression.Resource + ".Sample"; } // Check for unsupport construct float4x4(n) in hlsl, so convert to (float4x4)n if (expression.Name.Equals("float4x4")) { // Find float4x4 syntax part TextPart float4x4Part = expression.ConstituentSymbols[0] as TextPart; // Find value name TextPart valuePart = expression.ConstituentSymbols[2] as TextPart; if (valuePart != null && (valuePart.TextValue.Equals("0") || valuePart.TextValue.Equals(".0") || valuePart.TextValue.Equals(".0f") || valuePart.TextValue.Equals("0.0") || valuePart.TextValue.Equals("0.0f"))) { // Remove procedur name and value => "()" expression.ConstituentSymbols.Remove(float4x4Part); expression.ConstituentSymbols.Remove(valuePart); // Insert procedur name to bracket => (float4x4) expression.ConstituentSymbols.Insert(1, float4x4Part); // Insert value in last => (float4x4)n expression.ConstituentSymbols.Add(valuePart); } } // For other procedure .... like clamp, max, min, etc (in HLSL is not needed, maybe do it on GLSL) // Main CommonProcessor(stringBuilder, expression.ConstituentSymbols, metadata); }
/// <summary> /// Parses a procedure expression. /// </summary> public static void AcceptProcedure(string Text, int Start, out ProcedureExpression Expression, out int LastChar) { List<Statement> statements = new List<Statement>(); Statement statement; if (AcceptStatement(Text, Start, out statement, out LastChar)) { statements.Add(statement); while (true) { int nc; AcceptWhitespace(Text, LastChar, out nc); if (AcceptStatement(Text, nc, out statement, out nc)) { LastChar = nc; statements.Add(statement); } else { Expression = new ProcedureExpression(statements); return; } } } else { LastChar = Start; Expression = new ProcedureExpression(new List<Statement>()); } }