internal override ExpressionType EmitCs(EmitCodeContext codecontext) { if (ExpressionInside != null) { codecontext.Write(string.Empty, codecontext.Level); ExpressionInside.EmitCs(codecontext); codecontext.Write(";"); } return(ExpressionType.VoidType); }
/// <summary> /// Emit the C# method call, defined in the context class (codecontext.ContextName). /// </summary> /// <param name="codecontext"></param> /// <returns></returns> private ExpressionType TryEmitCsMethodCall(EmitCodeContext codecontext) { List <MethodDecl> matchingMethods = new List <MethodDecl>(); foreach (var decl in codecontext.Declarations.Methods) { if (decl.DeclMethodName == MethodName && decl.BodyCSharp != null) { if (decl.MethodArguments != null && decl.MethodArguments.Count != CallArguments.Count) { throw new GeneratorException(Position, "Invalid arguments count in method call " + MethodName); } matchingMethods.Add(decl); } } if (matchingMethods.Count > 1) { throw new GeneratorException(Position, "Ambiguous C# method call."); } if (matchingMethods.Count == 1) { MethodDecl decl = matchingMethods[0]; codecontext.Write(decl.GeneratedMethodName + "("); bool bFirst = true; if (CallArguments != null) { foreach (var x in CallArguments) { if (!bFirst) { codecontext.Write(", "); } else { bFirst = false; } x.EmitCs(codecontext); } } codecontext.Write(")"); return(decl.ReturnType); } return(null); }
private ExpressionType TryEmitClassConstruct(EmitCodeContext codecontext) { foreach (var decl in codecontext.Declarations.Classes.Values) { if (decl.ClassName == MethodName) { // emit // (new XXX(){ a = val1, b = val2 }); codecontext.Write("(new " + MethodName + "(){ "); for (int arg = 0; arg < CallArguments.Count; ++arg) { ExpressionAssign ass = CallArguments[arg] as ExpressionAssign; VariableUse lvalue; if (ass == null || (lvalue = ass.LValue as VariableUse) == null) { throw new GeneratorException(Position, "Argument " + arg + ": class construct arguments must be in a form of 'PropertyName = Expression'"); } if (arg > 0) { codecontext.Write(", "); } ExpressionType propType = decl.ContainsProperty(lvalue.VariableName); if (propType == null) { throw new GeneratorException(Position, lvalue.VariableName + " is not a property of " + decl.ClassName); } codecontext.Write(lvalue.VariableName + " = "); ExpressionType propValueType = ass.RValue.EmitCs(codecontext); if (!propValueType.Equals(propType)) { throw new GeneratorException(Position, "Type mishmash, " + propType.ToString() + " and " + propValueType.ToString()); } } codecontext.Write(" })"); return(new ExpressionUserType(decl.ClassName)); } } return(null); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { // l = r VariableUse lValueVariable = (VariableUse)LValue; ExpressionType lType = codecontext.GetLocalVarType(Position, lValueVariable.VariableName); if (lType == null) { throw new GeneratorException(Position, lValueVariable.VariableName + " is not declared."); } if (lType.ListOf != null) { throw new GeneratorException(Position, "Unable to assign to a list."); } // TODO: lValue cannot be the method argument, unable to assign to the method argument, only adding to lists or modifying object properties. // arg1 = .. // error // arg1.prop1 = ... // ok // arg2[] = ... // ok codecontext.Write(lValueVariable.VariableName + " = "); ExpressionType rType = RValue.EmitCs(codecontext); if (!(lType.Equals(rType))) { throw new GeneratorException(Position, "Type mishmash."); } return(lType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { ExpressionType lValueType = codecontext.GetLocalVarType(Position, lvalue.VariableName); if (lValueType == null) { throw new GeneratorException(Position, lvalue.VariableName + " not declared."); } if (lValueType.ListOf == null) { throw new GeneratorException(Position, "Unable to add an element to a non-list variable."); } ExpressionType rValueType; if (!lvalue.VariableName.Contains(".")) { // add an element directly // lvalue.AddElement( rvalue ); codecontext.Write(lvalue.VariableName); codecontext.Write(".AddElement("); rValueType = rvalue.EmitCs(codecontext); codecontext.Write(")"); } else { // element cannot be added directly // must be created action that add the element when list is actually enumerated // TODO: throw warning, can cause memory leaks, adding elements one-by-one through the actions. codecontext.Write("AddElementAction(" + scopeLocalVarName + ".context, _parameters, \"" + lvalue.VariableName + "\", " + lvalue.VariableName + ", "); rValueType = rvalue.EmitCs(codecontext); codecontext.Write(")"); } if (!rValueType.Equals(lValueType.ListOf)) { throw new GeneratorException(Position, "Type mishmash, adding an element of type " + rValueType.ToString() + " to the list of " + lValueType.ListOf.ToString()); } return(lValueType.ListOf); }
/// <summary> /// Emit variable read. /// </summary> /// <param name="codecontext"></param> /// <returns></returns> internal override ExpressionType EmitCs(EmitCodeContext codecontext) { ExpressionType varType = codecontext.GetLocalVarType(Position, VariableName); if (varType != null) { // VariableName codecontext.Write(VariableName); return(varType); } else { if (VariableName.Contains(".")) { throw new GeneratorException(Position, "Undeclared variable " + VariableName); } // ((string)__l["VariableName"]) // dynamic var codecontext.Write("(" + scopeLocalVarName + "[\"" + VariableName + "\"].ToString())"); return(ExpressionType.StringType); } }
/// <summary> /// Emit the binary operation expression. /// </summary> /// <param name="codecontext">Code context.</param> /// <param name="binaryOperator">Binary operator.</param> /// <param name="expectedLType">Expected left type, or null.</param> /// <param name="expectedRType">Expected right type, or null.</param> internal ExpressionType EmitBinaryExpr(EmitCodeContext codecontext, string binaryOperator, ExpressionType expectedLType, ExpressionType expectedRType) { codecontext.Write("(("); ExpressionType lType = LValue.EmitCs(codecontext); codecontext.Write(")" + binaryOperator + "("); ExpressionType rType = RValue.EmitCs(codecontext); codecontext.Write("))"); if (!lType.Equals(rType)) { throw new GeneratorException(Position, "Type mishmash!"); } if ((expectedLType != null && !expectedLType.Equals(lType)) || (expectedRType != null && !expectedRType.Equals(rType))) { throw new GeneratorException(Position, "Type mishmash!"); } return(lType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { ExpressionType condType, expr1Type, expr2Type; codecontext.Write("("); condType = ConditionExpr.EmitCs(codecontext); codecontext.Write(")?("); expr1Type = Expr1.EmitCs(codecontext); codecontext.Write("):("); expr2Type = Expr2.EmitCs(codecontext); codecontext.Write(")"); if (!condType.Equals(ExpressionType.BoolType)) { throw new GeneratorException(Position, "Condition must be of type bool."); } if (!expr1Type.Equals(expr2Type)) { throw new GeneratorException(Position, "Type mishmash, " + expr1Type.ToString() + " and " + expr2Type.ToString()); } return(expr1Type); }
/// <summary> /// /// </summary> /// <param name="codecontext"></param> /// <returns></returns> internal override ExpressionType EmitCs(EmitCodeContext codecontext) { codecontext.WriteLine("{"); codecontext.Level++; // push scope bool contextchanged = false; foreach (var x in DataContexts) { if (!contextchanged) { contextchanged = true; codecontext.Write(scopeLocalVarName + ".Push(" + scopeLocalVarName + ".context", codecontext.Level); } //.OpenContextDynamic(MethodName, new object[] { arg1, arg2, ... }) codecontext.Write(".OpenContextDynamic(\"" + x.MethodName + "\", new object[] {"); bool firstArg = true; foreach (var a in x.CallArguments) { if (!firstArg) { codecontext.Write(", "); } else { firstArg = false; } a.EmitCs(codecontext); } codecontext.Write("})"); } if (contextchanged) { codecontext.Write(", null);" + codecontext.Output.NewLine); } // emit statements foreach (var s in Statements) { s.EmitCs(codecontext); codecontext.Write(codecontext.Output.NewLine); } // pop scope if (contextchanged) { codecontext.WriteLine(scopeLocalVarName + ".Pop();"); } codecontext.Level--; codecontext.WriteLine("}"); return(ExpressionType.VoidType); }
/// <summary> /// Emit formatted value expression. /// </summary> /// <param name="codecontext"></param> /// <param name="format"></param> /// <returns>Value type.</returns> internal ExpressionType EmitValue(EmitCodeContext codecontext, string format) { if (Value == null) { throw new GeneratorException(Position, "Value cannot be null."); } // process the value on separated output MemoryStream valstr = new MemoryStream(); StreamWriter valoutput = new StreamWriter(valstr); EmitCodeContext valcontext = new EmitCodeContext(codecontext, valoutput); ExpressionType valType = Value.EmitCs(valcontext); valoutput.Flush(); // get value emitted expression valstr.Position = 0; codecontext.Write(string.Format(format, new StreamReader(valstr).ReadToEnd())); return(valType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { // process the value on separated output MemoryStream valstr = new MemoryStream(); StreamWriter valoutput = new StreamWriter(valstr); EmitCodeContext valcontext = new EmitCodeContext(codecontext, valoutput); ExpressionType valType = Value.EmitCs(valcontext); valoutput.Flush(); // get value emitted expression valstr.Position = 0; string valvalue = "(" + new StreamReader(valstr).ReadToEnd() + ")"; // check return types if (valType.Equals(NewType)) { codecontext.Write(valvalue); } else { string result = null; switch (valType.TypeName) { case ExpressionType.KnownTypes.TBool: switch (NewType.TypeName) { case ExpressionType.KnownTypes.TDouble: result = string.Format("{0}?(1.0):(0.0)", valvalue); break; case ExpressionType.KnownTypes.TInt: result = string.Format("{0}?(1):(0)", valvalue); break; case ExpressionType.KnownTypes.TString: result = string.Format("{0}?(\"true\"):(\"false\")", valvalue); break; } break; case ExpressionType.KnownTypes.TDateTime: switch (NewType.TypeName) { case ExpressionType.KnownTypes.TString: result = string.Format("{0}.ToString()", valvalue); break; } break; case ExpressionType.KnownTypes.TDouble: switch (NewType.TypeName) { case ExpressionType.KnownTypes.TBool: result = string.Format("{0}!=0.0", valvalue); break; case ExpressionType.KnownTypes.TInt: result = string.Format("(int){0}", valvalue); break; case ExpressionType.KnownTypes.TString: result = string.Format("{0}.ToString()", valvalue); break; } break; case ExpressionType.KnownTypes.TInt: switch (NewType.TypeName) { case ExpressionType.KnownTypes.TBool: result = string.Format("{0}!=0.0", valvalue); break; case ExpressionType.KnownTypes.TDouble: result = string.Format("(double){0}", valvalue); break; case ExpressionType.KnownTypes.TString: result = string.Format("{0}.ToString()", valvalue); break; } break; case ExpressionType.KnownTypes.TString: switch (NewType.TypeName) { case ExpressionType.KnownTypes.TBool: result = string.Format("({0}.ToLower()==\"true\")?true:false", valvalue); break; case ExpressionType.KnownTypes.TInt: result = string.Format("int.Parse{0}", valvalue); break; case ExpressionType.KnownTypes.TDouble: result = string.Format("double.Parse{0}", valvalue); break; case ExpressionType.KnownTypes.TDateTime: result = string.Format("DateTime.Parse{0}", valvalue); break; } break; default: if (NewType.TypeName == ExpressionType.KnownTypes.TString) { result = string.Format("{0}.ToString()", valvalue); // anything to string } break; } if (string.IsNullOrEmpty(result)) { throw new GeneratorException(Position, "Unable to explicitly type the expression from " + valType.ToString() + " to " + NewType.ToString() + "."); } codecontext.Write("(" + result + ")"); } // return(NewType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { codecontext.Write(CsCode); return(ExprType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { codecontext.Write("(new DateTime(\"" + Value.ToString() + "\"))"); return(ExpressionType.DateTimeType); }
private ExpressionType TryEmitExtractionMethodCall(EmitCodeContext codecontext) { List <MethodDecl> matchingMethods = new List <MethodDecl>(); foreach (var decl in codecontext.Declarations.Methods) { if (decl.DeclMethodName == MethodName && decl.Body != null) { if (decl.IsMainMethod) { throw new GeneratorException(Position, "main method cannot be called!"); } if (decl.MethodArguments.Count != CallArguments.Count) { throw new GeneratorException(Position, "Invalid arguments count in method call " + MethodName); } matchingMethods.Add(decl); } } if (matchingMethods.Count > 0) { codecontext.Write("ActionItem.AddAction( new ActionItem.ExtractionMethod[]{"); bool bFirstMethod = true; foreach (var decl in matchingMethods) { if (bFirstMethod) { bFirstMethod = false; } else { codecontext.Write(", "); } codecontext.Write(decl.GeneratedMethodName); } codecontext.Write("}, " + scopeLocalVarName + ".context, new LocalVariables() {" + codecontext.Output.NewLine); codecontext.Level++; MethodDecl somedecl = matchingMethods[0]; string cannotAddActionDict = null; for (int arg = 0; arg < CallArguments.Count; ++arg) { if (arg > 0) { codecontext.Write("," + codecontext.Output.NewLine); } codecontext.Write("{\"" + somedecl.MethodArguments[arg].VariableName + "\", ", codecontext.Level); ExpressionType t = CallArguments[arg].EmitCs(codecontext); codecontext.Write("}"); if (!t.Equals(somedecl.MethodArguments[arg].VariableType)) { throw new GeneratorException(Position, "Type mishmash."); } // check if the argument is able to add new action VariableUse varuse; if ((varuse = CallArguments[arg] as VariableUse) != null) { if (cannotAddActionDict != null) { cannotAddActionDict += ","; } cannotAddActionDict += "{\"" + somedecl.MethodArguments[arg].VariableName + "\",_parameters.CannotAddActionForVariable(\"" + varuse.VariableName + "\")}"; } } codecontext.Write(" }.SetCannotAddAction(new Dictionary<string,bool>(){" + cannotAddActionDict + "}))"); codecontext.Level--; return(ExpressionType.VoidType); } else { return(null); } }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { codecontext.Write(Value.ToString()); return(ExpressionType.IntType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { codecontext.Write(CsValue); return(ExpressionType.StringType); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { codecontext.Write(Value ? "true" : "false"); return(ExpressionType.BoolType); }
internal void EmitCs_Init(EmitCodeContext codecontext) { Dictionary <string, ExpressionType> contextVars = new Dictionary <string, ExpressionType>(); List <MethodDecl> mainMethods = new List <MethodDecl>(); // collect global vars, extraction arguments foreach (var m in codecontext.Declarations.Methods) { if (m.IsMainMethod) { mainMethods.Add(m); foreach (var arg in m.MethodArguments) { ExpressionType vartype; if (contextVars.TryGetValue(arg.VariableName, out vartype)) { if (vartype != arg.VariableType) { throw new GeneratorException(Position, "Two context variables with different type defined."); } } else { contextVars[arg.VariableName] = arg.VariableType; } } } } // emit properties codecontext.WriteLine("#region Public extracted data"); foreach (var v in contextVars) { codecontext.WriteLine("// " + v.Value.ToString() + " " + v.Key); if (v.Value.IsExtractionObject) { // emit prop codecontext.WriteLine("public readonly " + v.Value.CsPropertyTypeName + " " + v.Key + " = " + v.Value.CsPropertyRootInitValue + ";"); } /*else * { * // emit context parameter * codecontext.WriteLine("private readonly " + v.Value.CsArgumentTypeName + " " + v.Key + ";"); * }*/ } codecontext.WriteLine("#endregion" + codecontext.Output.NewLine); // // context arguments, initialization // string ctorArgs = null; string argsPass = null; foreach (var x in contextVars) { if (!x.Value.IsExtractionObject) { // argument if (ctorArgs != null) { ctorArgs += ", "; } if (argsPass != null) { argsPass += ", "; } ctorArgs = ctorArgs + x.Value.CsArgumentTypeName + " " + x.Key; argsPass = argsPass + x.Key; } } // emit initializing actions codecontext.WriteLine("#region Context construct"); codecontext.WriteLine("private void InitActionsToDo(" + ctorArgs + ")"); codecontext.WriteLine("{"); codecontext.Level++; foreach (var m in mainMethods) { codecontext.WriteLine("ActionItem.AddAction(" + m.GeneratedMethodName + ", InitialDataContext, new LocalVariables(){"); codecontext.Level++; bool bfirstarg = true; foreach (var arg in m.MethodArguments) { if (bfirstarg) { bfirstarg = false; } else { codecontext.Write("," + codecontext.Output.NewLine); } codecontext.Write("{\"" + arg.VariableName + "\", " + arg.VariableName + "}", codecontext.Level); } codecontext.Write("});" + codecontext.Output.NewLine); codecontext.Level--; } codecontext.Level--; codecontext.WriteLine("}"); // emit ctors codecontext.WriteLine("#region Constructors"); codecontext.WriteLine("public " + codecontext.ContextName + "(" + ctorArgs + "):base(){InitActionsToDo(" + argsPass + ");}"); codecontext.WriteLine("public " + codecontext.ContextName + "(" + ((ctorArgs == null) ? "" : (ctorArgs + ", ")) + "StorageBase cache):base(cache){InitActionsToDo(" + argsPass + ");}"); codecontext.WriteLine("#endregion"); codecontext.WriteLine("#endregion" + codecontext.Output.NewLine); }
internal override ExpressionType EmitCs(EmitCodeContext codecontext) { if (Body != null) { MethodCall foreachMethod = ForeachExpression as MethodCall; if (foreachMethod == null) { throw new GeneratorException(Position, "argument of foreach must be a method call"); } /* // emit this * foreach (var x in ForeachMethods.regexp(l.context, @"Porno\s+(?<Title>\w+)")) * { * l.Push(null, x); // or l.Push(x, null); * * {Body} * * l.Pop(); * } */ string foreachVarName = "__fe" + Position.StartLine + "_" + Position.StartColumn; // write foreach header codecontext.Write("foreach(var " + foreachVarName + " in ForeachMethods." + foreachMethod.MethodName + "(" + scopeLocalVarName + ".context", codecontext.Level); // method arguments List <ExpressionType> methodargs = new List <ExpressionType>(); foreach (var arg in foreachMethod.CallArguments) { codecontext.Write(", "); methodargs.Add(arg.EmitCs(codecontext)); } codecontext.Write("))" + codecontext.Output.NewLine); // check signature Type vartype = CheckMethodSignature(foreachMethod.MethodName, methodargs.ToArray()); // foreach block codecontext.WriteLine("{"); codecontext.Level++; string DataContextVar = (vartype == typeof(linqtoweb.Core.datacontext.DataContext)) ? foreachVarName : "null"; string VariablesVar = (vartype == typeof(linqtoweb.Core.extraction.LocalVariables)) ? foreachVarName : "null"; codecontext.WriteLine(scopeLocalVarName + ".Push(" + DataContextVar + "," + VariablesVar + ");"); // Body Body.EmitCs(codecontext); // codecontext.WriteLine(scopeLocalVarName + ".Pop();"); // codecontext.Level--; codecontext.WriteLine("}"); } return(ExpressionType.VoidType); }