public override void Interpret(Operator op, FunctionBlock block) { if (ScriptEngine.AnalyzeDebug) { Debug.LogWarning("Context function " + op.Identifier); } if (exprInter == null) { exprInter = Engine.GetPlugin <ExpressionInterpreter> (); } var any = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; var sCtx = block.FindStatement <ContextStatement> (v => v.InterpretInContext(op, block) != null && (v.ContextVar.IsContext || v.ContextVar.IsArg)); var contextVar = sCtx != null ? sCtx.ContextVar : null; //var contextVar = block.FindStatement<DeclareVariableStatement> (v => ); StringBuilder argsBuilder = new StringBuilder(); // if (((op.Context is Expression) && op.Args.Count + 1 != argsDef.Length) || // ((op.Context is Context) && op.Args.Count != argsDef.Length)) // { // Debug.Log ("Wrong amount of arguments"); // return; // } for (int i = 0; i < op.Args.Count; i++) { if (argsDef [i].ParameterType.IsSubclassOf(typeof(Delegate))) { argsBuilder.Append(exprInter.InterpretClosure(op.Args [i], block, argsDef [i].ParameterType).ExprString).Append(","); } else if (argsDef [i].ParameterType == typeof(string)) { argsBuilder.Append('(').Append(exprInter.InterpretExpression(op.Args [i], block).ExprString).Append(')').Append(".ToString()").Append(","); } else { argsBuilder.Append('(').Append(argsDef [i].ParameterType).Append(')').Append('(').Append(exprInter.InterpretExpression(op.Args [i], block).ExprString).Append(')').Append(","); } } if (op.Context is Expression) { if (argsDef [argsDef.Length - 1].ParameterType.IsSubclassOf(typeof(Delegate))) { argsBuilder. Append('('). Append(argsDef [argsDef.Length - 1].ParameterType). Append(')'). Append('('). Append(exprInter.InterpretClosure(op.Context as Expression, block, argsDef [argsDef.Length - 1].ParameterType).ExprString). Append(')'); } else if (argsDef [argsDef.Length - 1].ParameterType == typeof(string)) { argsBuilder.Append('(').Append(exprInter.InterpretExpression(op.Context as Expression, block).ExprString).Append(')').Append(".ToString()"); } else { argsBuilder. Append('('). Append(argsDef [argsDef.Length - 1].ParameterType). Append(')'). Append('('). Append(exprInter.InterpretExpression(op.Context as Expression, block).ExprString). Append(')'); } if (contextVar == null) { block.Statements.Add(string.Format("root.{0}({1});", funcName, argsBuilder)); } else { block.Statements.Add(string.Format("{2}.{0}({1});", funcName, argsBuilder, contextVar.Name)); } } else if (ctxInter != null) { if (op.Args.Count > 0) { argsBuilder.Length -= 1; } var ctx = op.Context as Context; FunctionBlock contextBlock = new FunctionBlock(block); block.Statements.Add(contextBlock); block = contextBlock; DeclareVariableStatement ctxVar = new DeclareVariableStatement(); ctxVar.Name = "FuncCtx" + DeclareVariableStatement.VariableId++; ctxVar.InitExpression = contextVar == null?string.Format("root.{0}({1});", funcName, argsBuilder) : string.Format("{2}.{0}({1});", funcName, argsBuilder, contextVar.Name); ctxVar.Type = returnType; ctxVar.IsContext = true; ContextStatement stmt = new ContextStatement(); stmt.ContextVar = ctxVar; stmt.InterpretInContext = ctxInter.InterpretInContext; block.Statements.Add(ctxVar); block.Statements.Add(stmt); IfStatement isNotNull = new IfStatement(); isNotNull.CheckExpression = String.Format("{0} != null", ctxVar.Name); isNotNull.TrueBlock = new FunctionBlock(block); block.Statements.Add(isNotNull); block = isNotNull.TrueBlock; for (int i = 0; i < ctx.Entries.Count; i++) { ops.GetInterpreter(ctx.Entries [i] as Operator, block).Interpret(ctx.Entries [i] as Operator, block); } } else { //Func doesn't return a context, while maybe allows for either lambda as value or context addition var lastArg = argsDef.Length > 0 ? argsDef [argsDef.Length - 1] : null; if (lastArg != null) { if (typeof(Delegate).IsAssignableFrom(lastArg.ParameterType)) { Debug.Log("LAMBDA!"); //Interpret as lambda LambdaStatement lambda = new LambdaStatement(); lambda.DelegateType = lastArg.ParameterType; var method = lastArg.ParameterType.GetMethod("Invoke"); lambda.Params = method.GetParameters(); lambda.Name = "Lambda" + DeclareVariableStatement.VariableId++; block.Statements.Add(lambda); lambda.Block = new FunctionBlock(block); //DeclareVariableStatement lastVar = null; foreach (var param in lambda.Params) { var argVar = new DeclareVariableStatement(); // lastVar = argVar; argVar.Name = param.Name; argVar.IsArg = true; argVar.Type = param.ParameterType; lambda.Block.Statements.Add(argVar); } //if (lastVar != null) // lastVar.IsContext = true; var retType = lambda.DelegateType.GetMethod("Invoke").ReturnType; bool hasReturn = false; if (retType != null && retType != typeof(void)) { hasReturn = true; lambda.Block.Statements.Add(new DeclareVariableStatement() { Name = "return_value", InitExpression = string.Format("default({0})", retType), IsReturn = true, Type = retType }); } foreach (var entry in (op.Context as Context).Entries) { var subOp = entry as Operator; ops.GetInterpreter(subOp, lambda.Block).Interpret(subOp, lambda.Block); } if (hasReturn) { lambda.Block.Statements.Add("return return_value;"); } //Don't forget to call a function and add an arugment argsBuilder.Append(lambda.Name); if (contextVar == null) { block.Statements.Add(string.Format("root.{0}({1});", funcName, argsBuilder)); } else { block.Statements.Add(string.Format("{2}.{0}({1});", funcName, argsBuilder, contextVar.Name)); } } else if (addContextInter != null) { //Interpret as new value DeclareVariableStatement newVar = new DeclareVariableStatement(); newVar.Name = "NewArg" + DeclareVariableStatement.VariableId++; newVar.IsContext = true; newVar.Type = lastArg.ParameterType; if (contextVar == null) { newVar.InitExpression = String.Format("root.AddComponent<{0}>()", newVar.Type); } else { newVar.InitExpression = String.Format("{0}.AddComponent<{0}>()", contextVar.Name, newVar.Type); } FunctionBlock contextBlock = new FunctionBlock(block); contextBlock.Statements.Add(newVar); addContextInter.Interpret(op, contextBlock); argsBuilder.Append(newVar.Name); if (contextVar == null) { contextBlock.Statements.Add(string.Format("root.{0}({1});", funcName, argsBuilder)); } else { contextBlock.Statements.Add(string.Format("{2}.{0}({1});", funcName, argsBuilder, contextVar.Name)); } block.Statements.Add(contextBlock); } } } }
public override void Interpret(Operator op, FunctionBlock block) { base.Interpret(op, block); if (interpret) { if (ScriptEngine.AnalyzeDebug) { Debug.LogFormat("Property {0} was interpreted by ContextPropertyInterpreter {1} already", op, propName); } return; } if (!(op.Context is Context)) { if (ScriptEngine.AnalyzeDebug) { Debug.LogFormat("Property context switch {0} has no context", op); } return; } if (ops == null) { ops = Engine.GetPlugin <EventFunctionOperators> (); } var varName = op.Identifier as string; FunctionBlock contextBlock = new FunctionBlock(block, block.Method, block.Type); block.Statements.Add(contextBlock); DeclareVariableStatement declareVar = new DeclareVariableStatement(); declareVar.Type = propType; declareVar.Name = "subContext" + DeclareVariableStatement.VariableId++; declareVar.IsContext = true; DeclareVariableStatement contextVar = block.FindStatement <DeclareVariableStatement> (v => v.Name == varName); if (contextVar == null) { var sCtx = block.FindStatement <ContextStatement> (v => v.InterpretInContext(op, block) != null && v.ContextVar.IsContext); contextVar = sCtx != null ? sCtx.ContextVar : null; } if (contextVar == null) { declareVar.InitExpression = String.Format("root.{0}", propName); } else { declareVar.InitExpression = String.Format("{1}.{0}", propName, contextVar.Name); } contextBlock.Statements.Add(declareVar); contextBlock.Statements.Add(new ContextStatement() { ContextVar = declareVar, InterpretInContext = InterpretInContext }); IfStatement isNotNull = new IfStatement(); isNotNull.CheckExpression = String.Format("{0} != null", declareVar.Name); isNotNull.TrueBlock = new FunctionBlock(contextBlock); contextBlock.Statements.Add(isNotNull); contextBlock = isNotNull.TrueBlock; foreach (var entry in (op.Context as Context).Entries) { //Debug.LogFormat("Interpreting {0} as part of {1} context", (entry as Operator).Identifier, op.Identifier); var subOp = entry as Operator; if (subOp == null) { continue; } FunctionOperatorInterpreter opInter = null; if ((opInter = ops.GetInterpreter(subOp, contextBlock)) == null) { if (!contextSwitches.TryGetValue(subOp.Identifier as string, out opInter)) { if (!functions.TryGetValue(subOp.Identifier as string, out opInter)) { if (!properties.TryGetValue(subOp.Identifier as string, out opInter)) { //Debug.LogFormat ("Can't interpret context operator {1} in {0}", block.Method.Name, subOp.Identifier); continue; } } } } opInter.Interpret(subOp, contextBlock); } }
public override void Interpret(Operator op, FunctionBlock block) { if (ops == null) { ops = Engine.GetPlugin <EventFunctionOperators> (); } FunctionBlock contextBlock = new FunctionBlock(block, block.Method, block.Type); block.Statements.Add(contextBlock); DeclareVariableStatement addVar = block.FindStatement <DeclareVariableStatement> (v => v.Name == op.Identifier as string); bool setContext = false; if (addVar != null && !addVar.IsContext) { setContext = addVar.IsContext = true; } if (addVar == null) { addVar = block.FindStatement <DeclareVariableStatement> (v => v.IsContext && v.Type == contextType); } //TODO: probably will fail DeclareVariableStatement contextVar = contextType == typeof(GameObject)? addVar : block.FindStatement <DeclareVariableStatement> (v => v.IsContext && v.Type == typeof(GameObject) && v != addVar); DeclareVariableStatement declareVar = null; if (addVar == null) { declareVar = new DeclareVariableStatement(); declareVar.Type = contextType; declareVar.Name = "subContext" + DeclareVariableStatement.VariableId++; declareVar.IsContext = true; if (contextVar == null) { declareVar.InitExpression = String.Format("({0})root.GetComponent(typeof({0}))", contextType); } else { declareVar.InitExpression = String.Format("({0}){1}.GetComponent(typeof({0}))", contextType, contextVar.Name); } contextBlock.Statements.Add(declareVar); } else { declareVar = addVar; } contextBlock.Statements.Add(new ContextStatement() { ContextVar = declareVar, InterpretInContext = InterpretInContext }); IfStatement isNotNull = new IfStatement(); isNotNull.CheckExpression = String.Format("{0} != null", declareVar.Name); isNotNull.TrueBlock = new FunctionBlock(contextBlock); contextBlock.Statements.Add(isNotNull); contextBlock = isNotNull.TrueBlock; contextBlock.Statements.Add(new DeclareVariableStatement() { Name = declareVar.Name, IsArg = true, IsContext = true, Type = declareVar.Type }); foreach (var entry in (op.Context as Context).Entries) { var subOp = entry as Operator; if (subOp == null) { continue; } FunctionOperatorInterpreter opInter = null; if ((opInter = ops.GetInterpreter(subOp, contextBlock)) == null) { if (!contextSwitches.TryGetValue(subOp.Identifier as string, out opInter)) { if (!functions.TryGetValue(subOp.Identifier as string, out opInter)) { if (!properties.TryGetValue(subOp.Identifier as string, out opInter)) { Debug.LogWarningFormat("Can't interpret context operator {1} in {0}", block.Method.Name, subOp.Identifier); continue; } } } } if (ScriptEngine.AnalyzeDebug) { Debug.LogFormat("Interpret {0} via {1}", subOp.Identifier, opInter); } opInter.Interpret(subOp, contextBlock); } if (setContext) { addVar.IsContext = false; } }