예제 #1
0
        internal override ExpressionType EmitCs(EmitCodeContext codecontext)
        {
            if (ExpressionInside != null)
            {
                codecontext.Write(string.Empty, codecontext.Level);
                ExpressionInside.EmitCs(codecontext);
                codecontext.Write(";");
            }

            return(ExpressionType.VoidType);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        /// <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);
            }
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        /// <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);
        }
예제 #10
0
        /// <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);
        }
예제 #11
0
        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);
        }
예제 #12
0
 internal override ExpressionType EmitCs(EmitCodeContext codecontext)
 {
     codecontext.Write(CsCode);
     return(ExprType);
 }
예제 #13
0
        internal override ExpressionType EmitCs(EmitCodeContext codecontext)
        {
            codecontext.Write("(new DateTime(\"" + Value.ToString() + "\"))");

            return(ExpressionType.DateTimeType);
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        internal override ExpressionType EmitCs(EmitCodeContext codecontext)
        {
            codecontext.Write(Value.ToString());

            return(ExpressionType.IntType);
        }
예제 #16
0
        internal override ExpressionType EmitCs(EmitCodeContext codecontext)
        {
            codecontext.Write(CsValue);

            return(ExpressionType.StringType);
        }
예제 #17
0
        internal override ExpressionType EmitCs(EmitCodeContext codecontext)
        {
            codecontext.Write(Value ? "true" : "false");

            return(ExpressionType.BoolType);
        }
예제 #18
0
        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);
        }
예제 #19
0
        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);
        }