Example #1
0
 /// <summary>
 /// Emit the code to create an array of variable arguments and evaluate
 /// and store each argument in the array. On exit, the address of the
 /// array is left on the top of the stack.
 /// </summary>
 /// <param name="cg">A CodeGenerator object</param>
 /// <param name="returnType">The type required by the caller</param>
 /// <returns>The symbol type of the value generated</returns>
 public override SymType Generate(CodeGenerator cg, SymType returnType)
 {
     if (cg == null) {
         throw new ArgumentNullException("cg");
     }
     int argCount = Nodes.Count;
     cg.Emitter.CreateSimpleArray(argCount, typeof(Object));
     for (int c = 0; c < argCount; ++c) {
         cg.Emitter.Dup();
         cg.Emitter.LoadInteger(c);
         cg.Emitter.StoreElementReference(cg.GenerateExpression(SymType.NONE, Nodes[c]));
     }
     return SymType.VARARG;
 }
Example #2
0
 /// <summary>
 /// Emit the code to generate an arithmetic conditional block.
 /// </summary>
 /// <param name="cg">A code generator object</param>
 public override void Generate(CodeGenerator cg)
 {
     if (cg == null) {
         throw new ArgumentNullException("cg");
     }
     SymType exprType = cg.GenerateExpression(SymType.NONE, ValueExpression);
     Symbol label1 = cg.GetLabel(Nodes[0]);
     Symbol label2 = cg.GetLabel(Nodes[1]);
     Symbol label3 = cg.GetLabel(Nodes[2]);
     LocalDescriptor tempIndex = cg.Emitter.GetTemporary(Symbol.SymTypeToSystemType(exprType));
     cg.Emitter.StoreLocal(tempIndex);
     cg.Emitter.LoadLocal(tempIndex);
     cg.Emitter.LoadValue(exprType, new Variant(0));
     cg.Emitter.BranchLess((Label)label1.Info);
     cg.Emitter.LoadLocal(tempIndex);
     cg.Emitter.LoadValue(exprType, new Variant(0));
     cg.Emitter.BranchEqual((Label)label2.Info);
     cg.Emitter.Branch((Label)label3.Info);
     cg.Emitter.ReleaseTemporary(tempIndex);
 }
Example #3
0
        // Generate the code for a string concatenation operator
        SymType GenerateConcat(CodeGenerator cg)
        {
            Type charType = Symbol.SymTypeToSystemType(Left.Type);

            cg.GenerateExpression(Left.Type, Left);
            cg.GenerateExpression(Left.Type, Right);

            cg.Emitter.Call(cg.GetMethodForType(charType, "Concat", new [] { charType, charType }));
            return Left.Type;
        }
Example #4
0
        /// <summary>
        /// Emit the code to generate a while loop.
        /// </summary>
        /// <param name="cg">A code generator object</param>
        void GenerateWhileLoop(CodeGenerator cg)
        {
            Label loopStart = cg.Emitter.CreateLabel();
            Label loopEnd = cg.Emitter.CreateLabel();

            // Skip the loop if the expression is a constant false
            if (StartExpression.IsConstant && !StartExpression.Value.BoolValue) {
                return;
            }

            cg.Emitter.MarkLabel(loopStart);
            cg.GenerateExpression(SymType.BOOLEAN, StartExpression);
            cg.Emitter.BranchIfFalse(loopEnd);
            CollectionParseNode block = LoopBody;
            foreach (ParseNode t in block.Nodes) {
                t.Generate(cg);
            }
            cg.Emitter.Branch(loopStart);
            cg.Emitter.MarkLabel(loopEnd);
        }
Example #5
0
        // Emit the appropriate store parameter index opcode.
        void GenerateStoreArgument(CodeGenerator cg, Symbol sym)
        {
            switch (sym.Linkage) {
                case SymLinkage.BYVAL:
                    cg.GenerateExpression(sym.Type, ValueExpression);
                    cg.Emitter.StoreParameter(sym.ParameterIndex);
                    break;

                case SymLinkage.BYREF:
                    cg.Emitter.LoadParameter(sym.ParameterIndex);
                    cg.GenerateExpression(sym.Type, ValueExpression);
                    cg.Emitter.StoreIndirect(sym.Type);
                    break;
            }
        }
Example #6
0
        // Generate the code to write an expression to a substring represented
        // by an identifier which should be fixed string type.
        void GenerateSaveSubstring(CodeGenerator cg, SymType charType)
        {
            Type baseType = Symbol.SymTypeToSystemType(charType);

            // Optimise for constant start/end values
            if (Identifier.SubstringStart.IsConstant) {
                int startIndex = Identifier.SubstringStart.Value.IntValue - 1;
                cg.Emitter.LoadInteger(startIndex);
            } else {
                cg.GenerateExpression(SymType.INTEGER, Identifier.SubstringStart);
                cg.Emitter.LoadInteger(1);
                cg.Emitter.Sub(SymType.INTEGER);
            }
            if (Identifier.SubstringEnd == null) {
                cg.Emitter.LoadInteger(Identifier.Symbol.FullType.Width);
            } else {
                if (Identifier.SubstringEnd.IsConstant) {
                    int endIndex = Identifier.SubstringEnd.Value.IntValue - 1;
                    cg.Emitter.LoadInteger(endIndex);
                } else {
                    cg.GenerateExpression(SymType.INTEGER, Identifier.SubstringEnd);
                    cg.Emitter.LoadInteger(1);
                    cg.Emitter.Sub(SymType.INTEGER);
                }
            }
            cg.Emitter.Call(cg.GetMethodForType(typeof(JComLib.FixedString), "Set", new [] { baseType, typeof(int), typeof(int) }));
        }
Example #7
0
 // Generate the code for a binary subtraction operator
 SymType GenerateSub(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Left);
     cg.GenerateExpression(Type, Right);
     cg.Emitter.Sub(Type);
     return Type;
 }
Example #8
0
 // Generate the code for a logical Less Than operator
 SymType GenerateLt(CodeGenerator cg)
 {
     SymType neededType = TypePromotion(Left, Right);
     cg.GenerateExpression(neededType, Left);
     cg.GenerateExpression(neededType, Right);
     if (Symbol.IsCharType(neededType)) {
         Type charType = Symbol.SymTypeToSystemType(neededType);
         cg.Emitter.Call(cg.GetMethodForType(charType, "Compare", new [] {charType, charType}));
         cg.Emitter.LoadInteger(0);
     }
     cg.Emitter.CompareLesser();
     return Type;
 }
Example #9
0
 // Generate the code for a unary NOT logical operator
 SymType GenerateNot(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Operand);
     cg.Emitter.LoadInteger(0);
     cg.Emitter.CompareEquals();
     return Type;
 }
Example #10
0
 // Generate the code for a unary minus operator
 SymType GenerateMinus(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Operand);
     cg.Emitter.Neg(Type);
     return Type;
 }
Example #11
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="cg">A code generator object</param>
        public override void Generate(CodeGenerator cg)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            int switchCount = _caseList.Count;

            SymType exprType = cg.GenerateExpression(SymType.NONE, CompareExpression);
            if (switchCount == 1) {
                cg.GenerateExpression(exprType, _caseList[0]);
                Symbol sym = cg.GetLabel(_labelList[0]);
                cg.Emitter.BranchEqual((Label)sym.Info);
            } else {
                LocalDescriptor index = cg.Emitter.GetTemporary(Symbol.SymTypeToSystemType(exprType));
                cg.Emitter.StoreLocal(index);
                for (int switchIndex = 0; switchIndex < switchCount; ++switchIndex) {
                    cg.Emitter.LoadLocal(index);
                    cg.GenerateExpression(exprType, _caseList[switchIndex]);
                    Symbol sym = cg.GetLabel(_labelList[switchIndex]);
                    cg.Emitter.BranchEqual((Label)sym.Info);
                }
                cg.Emitter.ReleaseTemporary(index);
            }
        }
Example #12
0
        /// <summary>
        /// Generate the code to push one parameter onto the caller stack. There are
        /// three different approaches here:
        /// 
        /// 1. Passing a defined variable. We either pass the address of the
        ///    variable (which may be local, parameter or static) if the corresponding
        ///    argument is BYREF, or we pass the value.
        /// 2. Passing a computed value. A computed value has no storage so if the
        ///    corresponding argument is BYREF, we need to allocate storage for it
        ///    and pass the address of the storage.
        /// 3. Finally, a computed value where the argument is BYVAL is passed on
        ///    the stack.
        /// 
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="symParam">Symbol entry for the called function</param>
        /// <param name="locals">A Temporaries collection for any local temporaries</param>
        /// <returns>The system type corresponding to this parameter.</returns>
        public Type Generate(CodeGenerator cg, Symbol symParam, Temporaries locals)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (locals == null) {
                throw new ArgumentNullException("locals");
            }

            // Set some flags up-front
            bool isByRef = (symParam != null) ? symParam.IsByRef : IsByRef;
            bool isArray = (symParam != null) && symParam.IsArray;

            // The argument is an array, so the source must either be an array or
            // an array reference.
            if (isArray && _paramNode.ID == ParseID.IDENT) {
                IdentifierParseNode identNode = (IdentifierParseNode)_paramNode;
                Symbol symIdent = identNode.Symbol;
                if (symIdent.IsArray) {
                    GenerateLoadSubArray(cg, identNode, symParam, locals);
                    return symIdent.SystemType;
                }
            }

            // Parameter is an identifier. If passing by reference, pass the address
            // of the identifier in the local context. Otherwise extract and pass the
            // value.
            if (_paramNode.ID == ParseID.IDENT) {
                IdentifierParseNode identNode = (IdentifierParseNode)_paramNode;
                SymType identType = identNode.Type;
                Symbol symIdent = identNode.Symbol;

                if (!symIdent.IsInline && !identNode.HasSubstring) {
                    // If we're passing an existing parameter, it is already
                    // a reference so don't double it up.
                    if (symIdent.IsParameter) {
                        cg.Emitter.LoadParameter(symIdent.ParameterIndex);
                        if (!isByRef && symIdent.IsValueType) {
                            cg.Emitter.LoadIndirect(identType);
                        }
                    } else {
                        if (symIdent.IsArray && !identNode.HasIndexes) {
                            cg.GenerateLoadArray(identNode, false);
                            return symIdent.SystemType;
                        }
                        if (isByRef) {
                            cg.LoadAddress(identNode);
                        } else {
                            identNode.Generate(cg);
                            if (symParam != null) {
                                if (!symParam.IsMethod) {
                                    cg.Emitter.ConvertType(identNode.Type, symParam.Type);
                                }
                                identType = symParam.Type;
                            }
                        }
                    }
                    Type paramType = Symbol.SymTypeToSystemType(identType);
                    if (isByRef) {
                        paramType = paramType.MakeByRefType();
                    }
                    return paramType;
                }
            }

            // For reference function parameters, if this argument is not an
            // addressable object, such as a literal value or an expression,
            // then we need to generate local storage for the result and pass
            // the address of that.
            if (isByRef) {
                LocalDescriptor index = locals.New(_paramNode.Type);

                SymType exprType = cg.GenerateExpression(_paramNode.Type, _paramNode);
                cg.Emitter.StoreLocal(index);
                cg.Emitter.LoadLocalAddress(index);
                return Symbol.SymTypeToSystemType(exprType).MakeByRefType();
            }

            // Byval argument passing
            SymType neededType = (symParam != null) ? symParam.Type : Type;
            SymType thisType = cg.GenerateExpression(neededType, _paramNode);
            if (symParam != null) {
                thisType = symParam.Type;
            }
            return Symbol.SymTypeToSystemType(thisType);
        }
Example #13
0
        // Generate the code to extract a substring from the character string
        // at the top of the stack.
        SymType GenerateLoadSubstring(CodeGenerator cg)
        {
            Type charType = Symbol.SymTypeToSystemType(Type);

            cg.GenerateExpression(SymType.INTEGER, SubstringStart);
            cg.Emitter.LoadInteger(1);
            cg.Emitter.Sub(SymType.INTEGER);
            if (SubstringEnd == null) {
                cg.Emitter.Call(cg.GetMethodForType(charType, "Substring", new [] { typeof(int) }));
            } else {
                cg.Emitter.Dup();
                cg.GenerateExpression(SymType.INTEGER, SubstringEnd);
                cg.Emitter.Sub(SymType.INTEGER);
                cg.Emitter.Neg(SymType.INTEGER);
                cg.Emitter.Call(cg.GetMethodForType(charType, "Substring", new [] { typeof(int), typeof(int) }));
            }
            return Type;
        }
Example #14
0
        // Emit the code to insert inline code from a symbol. If the identifier
        // represents an inline function then the parse tree for each argument is
        // assigned to its parameters.
        void GenerateInline(CodeGenerator cg)
        {
            Symbol sym = Symbol;

            if (Indexes != null) {
                int paramIndex = 0;
                foreach (ParseNode param in Indexes) {
                    if (sym.Parameters != null && paramIndex < sym.Parameters.Count) {
                        Symbol symParam = sym.Parameters[paramIndex];
                        symParam.Class = SymClass.INLINE;
                        symParam.InlineValue = param;
                        symParam.FullType = new SymFullType(param.Type);
                        ++paramIndex;
                    }
                }
            }

            // Because we may have adjusted the type of the parameters based
            // on the assigned values, we now need to rescan the tree and
            // equalise and fix the types on the nodes.
            AdjustNodeType(sym.InlineValue);
            cg.GenerateExpression(sym.Type, sym.InlineValue);
        }
Example #15
0
 // Generate the code for a binary division operator
 SymType GenerateDivide(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Left);
     cg.GenerateExpression(Type, Right);
     cg.Emitter.Div(Type);
     return Type;
 }
Example #16
0
 // Generate the code for a binary exponentiation operator
 SymType GenerateExp(CodeGenerator cg)
 {
     cg.GenerateExpression(SymType.DOUBLE, Left);
     cg.GenerateExpression(SymType.DOUBLE, Right);
     cg.Emitter.Call(cg.GetMethodForType(typeof(Math), "Pow", new [] {typeof(double), typeof(double)}));
     return SymType.DOUBLE;
 }
Example #17
0
        /// <summary>
        /// Emit the code to generate a GOTO statement.
        /// </summary>
        /// <param name="cg">A code generator object</param>
        public override void Generate(CodeGenerator cg)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (ValueExpression == null) {
                Symbol sym = cg.GetLabel(Nodes[0]);
                cg.Emitter.Branch((Label)sym.Info);
            } else {
                Collection<ParseNode> labelNodes = Nodes;

                if (labelNodes == null || labelNodes.Count == 0) {
                    labelNodes = cg.CurrentProcedure.LabelList;
                }

                Label [] jumpTable = new Label[labelNodes.Count];
                for (int c = 0; c < labelNodes.Count; ++c) {
                    Symbol sym = cg.GetLabel(labelNodes[c]);
                    if (sym.Type == SymType.LABEL) {
                        jumpTable[c] = (Label)sym.Info;
                    }
                }
                cg.GenerateExpression(SymType.INTEGER, ValueExpression);
                if (!IsZeroBased) {
                    cg.Emitter.LoadInteger(1);
                    cg.Emitter.Sub(SymType.INTEGER);
                }
                cg.Emitter.Switch(jumpTable);
            }
        }
Example #18
0
 // Generate the code for a logical Not Equals operator
 SymType GenerateNe(CodeGenerator cg)
 {
     SymType neededType = TypePromotion(Left, Right);
     cg.GenerateExpression(neededType, Left);
     cg.GenerateExpression(neededType, Right);
     if (Symbol.IsCharType(neededType)) {
         Type charType = Symbol.SymTypeToSystemType(neededType);
         cg.Emitter.Call(cg.GetMethodForType(charType, "op_Equality", new [] {charType, charType}));
     } else {
         cg.Emitter.CompareEquals();
     }
     cg.Emitter.LoadInteger(1);
     cg.Emitter.Xor();
     return Type;
 }
Example #19
0
        /// <summary>
        /// Emit the code to generate a call to the READ library function. A
        /// parse node must be provided which evaluates to the address of the
        /// identifier into which the data is read.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="node">A parse node for the READ identifier</param>
        public override void Generate(CodeGenerator cg, ParseNode node)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (node is LoopParseNode) {
                LoopParseNode loopNode = (LoopParseNode)node;
                loopNode.Callback = this;
                loopNode.Generate(cg);
            } else {
                Type readManagerType = typeof(JComLib.ReadManager);
                List<Type> readParamTypes = new List<Type>();

                cg.Emitter.LoadLocal(ReadManagerIndex);
                readParamTypes.Add(readManagerType);

                readParamTypes.AddRange(ReadParamsNode.Generate(cg));

                if (node is IdentifierParseNode) {
                    IdentifierParseNode identNode = (IdentifierParseNode)node;
                    if (identNode.IsArrayBase) {
                        cg.Emitter.LoadInteger(identNode.Symbol.ArraySize);
                        identNode.Generate(cg);

                        readParamTypes.Add(typeof(int));
                        readParamTypes.Add(Symbol.SymTypeToSystemType(identNode.Symbol.Type).MakeArrayType());
                    } else if (identNode.HasSubstring) {
                        cg.GenerateExpression(SymType.INTEGER, identNode.SubstringStart);
                        if (identNode.SubstringEnd != null) {
                            cg.GenerateExpression(SymType.INTEGER, identNode.SubstringEnd);
                        } else {
                            cg.Emitter.LoadInteger(-1);
                        }
                        cg.LoadAddress(identNode);
                        readParamTypes.Add(typeof(int));
                        readParamTypes.Add(typeof(int));
                        readParamTypes.Add(Symbol.SymTypeToSystemType(identNode.Symbol.Type).MakeByRefType());
                    } else {
                        cg.LoadAddress(identNode);
                        readParamTypes.Add(Symbol.SymTypeToSystemType(identNode.Symbol.Type).MakeByRefType());
                    }
                }

                cg.Emitter.Call(cg.GetMethodForType(_libraryName, _name, readParamTypes.ToArray()));
                cg.Emitter.StoreLocal(ReturnIndex);

                if (EndLabel != null) {
                    cg.Emitter.LoadLocal(ReturnIndex);
                    cg.Emitter.LoadInteger(0);
                    cg.Emitter.BranchEqual((Label)EndLabel.Symbol.Info);
                }
                if (ErrLabel != null) {
                    cg.Emitter.LoadLocal(ReturnIndex);
                    cg.Emitter.LoadInteger(-1);
                    cg.Emitter.BranchEqual((Label)ErrLabel.Symbol.Info);
                }
            }
        }
Example #20
0
 // Generate the code for an exclusive OR operator
 SymType GenerateXor(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Left);
     cg.GenerateExpression(Type, Right);
     cg.Emitter.Xor();
     return Type;
 }
Example #21
0
        /// <summary>
        /// Emit the code to generate a conditional block. Optimisation
        /// is performed on the tests so that any conditional which is
        /// a constant true causes the block to be executed and the whole
        /// loop code generation terminated after that block. A constant
        /// false causes the block to be ignored.
        /// </summary>
        /// <param name="cg">A code generator object</param>
        public override void Generate(CodeGenerator cg)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            int index = 0;

            Label labFalse = cg.Emitter.CreateLabel(); // Destination of false condition
            Label labExit = cg.Emitter.CreateLabel();  // Exit from entire IF statement

            while (index < _exprList.Count) {
                bool isLastBlock = (index == _exprList.Count - 1);
                bool skipBlock = false;

                ParseNode expr = _exprList[index];
                if (expr != null) {
                    if (expr.IsConstant) {
                        if (expr.Value.BoolValue) {
                            isLastBlock = true;
                        } else {
                            skipBlock = true;
                        }
                    } else {
                        cg.GenerateExpression(SymType.BOOLEAN, _exprList[index]);
                        cg.Emitter.BranchIfFalse(isLastBlock ? labExit : labFalse);
                    }
                }
                if (!skipBlock) {
                    CollectionParseNode body = _bodyList[index];
                    foreach (ParseNode node in body.Nodes) {
                        node.Generate(cg);
                    }
                }
                if (!isLastBlock) {
                    if (!skipBlock) {
                        cg.Emitter.Branch(labExit);
                        cg.Emitter.MarkLabel(labFalse);
                        labFalse = cg.Emitter.CreateLabel();
                    }
                } else {
                    break;
                }
                ++index;
            }
            cg.Emitter.MarkLabel(labExit);
        }
Example #22
0
        // Emit code that saves the result of an expression to an array element.
        void GenerateSaveToArray(CodeGenerator cg)
        {
            Symbol sym = Identifier.Symbol;

            Debug.Assert(sym.IsArray);
            if (Identifier.IsArrayBase) {
                if (sym.IsParameter) {
                    GenerateStoreArgument(cg, sym);
                } else {
                    cg.GenerateExpression(SymType.NONE, ValueExpression);
                    cg.Emitter.StoreLocal(sym.Index);
                }
                return;
            }

            cg.GenerateLoadArrayAddress(Identifier);

            if (Identifier.HasSubstring) {
                cg.Emitter.LoadArrayElement(sym);
                cg.GenerateExpression(SymType.FIXEDCHAR, ValueExpression);
                GenerateSaveSubstring(cg, SymType.FIXEDCHAR);
                return;
            }

            if (sym.Type == SymType.FIXEDCHAR) {
                cg.Emitter.LoadArrayElement(sym);
                cg.GenerateExpression(SymType.NONE, ValueExpression);
                cg.Emitter.Call(cg.GetMethodForType(typeof(JComLib.FixedString), "Set", new[] { Symbol.SymTypeToSystemType(ValueExpression.Type) }));
                return;
            }

            cg.GenerateExpression(sym.Type, ValueExpression);
            cg.Emitter.StoreArrayElement(sym);
        }
Example #23
0
 // Emit the code that computes the number of iterations that the
 // loop requires.
 void GenerateLoopCount(CodeGenerator cg, Symbol sym, LocalDescriptor stepVar)
 {
     cg.GenerateExpression(sym.Type, EndExpression);
     if (StartExpression.IsConstant && StartExpression.Value.IntValue == 0) {
         // Start index is zero so no initial subtraction required.
         cg.GenerateExpression(sym.Type, StartExpression);
         cg.Emitter.StoreLocal(sym.Index);
     } else {
         cg.GenerateExpression(sym.Type, StartExpression);
         cg.Emitter.Dup();
         cg.Emitter.StoreLocal(sym.Index);
         cg.Emitter.Sub(sym.Type);
     }
     if (StepExpression.IsConstant) {
         int stepValue = StepExpression.Value.IntValue;
         cg.Emitter.LoadInteger(stepValue);
         cg.Emitter.Add(sym.Type);
         if (stepValue != 1) {
             cg.Emitter.LoadInteger(stepValue);
             cg.Emitter.Div(sym.Type);
         }
     } else {
         cg.GenerateExpression(sym.Type, StepExpression);
         cg.Emitter.Dup();
         cg.Emitter.StoreLocal(stepVar);
         cg.Emitter.Add(sym.Type);
         cg.Emitter.LoadLocal(stepVar);
         cg.Emitter.Div(sym.Type);
     }
     cg.Emitter.ConvertType(sym.Type, SymType.INTEGER);
 }
Example #24
0
        /// <summary>
        /// Emit the code to generate the assignment of an expression
        /// to an identifier. Various forms are permitted:
        /// 
        ///   identifier = value
        ///   identifier(array_indexes) = value
        ///   array = another_array
        ///   identifier(substring) = value
        /// 
        /// </summary>
        /// <param name="cg">A code generator object</param>
        public override void Generate(CodeGenerator cg)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }

            Symbol sym = Identifier.Symbol;

            if (sym.IsArray) {
                GenerateSaveToArray(cg);
                return;
            }
            if (Identifier.HasSubstring) {
                if (sym.IsParameter) {
                    cg.Emitter.LoadParameter(sym.ParameterIndex);
                } else {
                    cg.Emitter.LoadLocal(sym.Index);
                }
                SymType exprType = cg.GenerateExpression(SymType.NONE, ValueExpression);
                GenerateSaveSubstring(cg, exprType);
                return;
            }
            if (!sym.IsValueType) {
                if (sym.IsParameter) {
                    cg.Emitter.LoadParameter(sym.ParameterIndex);
                } else {
                    cg.Emitter.LoadLocal(sym.Index);
                }
                SymType exprType = cg.GenerateExpression(SymType.NONE, ValueExpression);
                if (sym.Type == SymType.FIXEDCHAR) {
                    MethodInfo meth = cg.GetMethodForType(typeof(JComLib.FixedString), "Set", new [] { Symbol.SymTypeToSystemType(exprType) });
                    cg.Emitter.Call(meth);
                }
                return;
            }
            if (sym.IsLocal) {
                cg.GenerateExpression(sym.Type, ValueExpression);
                cg.StoreLocal(sym);
                return;
            }
            GenerateStoreArgument(cg, sym);
        }
Example #25
0
 /// <summary>
 /// Generate the code to emit a procedure.
 /// </summary>
 /// <param name="cg">A CodeGenerator object</param>
 public override void Generate(CodeGenerator cg)
 {
     if (cg == null) {
         throw new ArgumentNullException("cg");
     }
     Symbol retVal = cg.CurrentProcedure.ProcedureSymbol.RetVal;
     if (retVal != null) {
         if (ReturnExpression != null) {
             SymType thisType = cg.GenerateExpression(SymType.NONE, ReturnExpression);
             cg.Emitter.ConvertType(thisType, retVal.Type);
         }
         else {
             if (retVal.Index == null) {
                 cg.Error(string.Format("Function {0} does not return a value", cg.CurrentProcedure.ProcedureSymbol.Name));
             }
             cg.Emitter.LoadLocal(retVal.Index);
         }
     } else {
         // For alternate return, if the method is marked as supporting
         // them then it will be compiled as a function. So it must always
         // have a return value. A value of 0 means the default behaviour
         // (i.e. none of the labels specified are picked).
         if (cg.CurrentProcedure.AlternateReturnCount > 0) {
             if (ReturnExpression != null) {
                 cg.GenerateExpression(SymType.INTEGER, ReturnExpression);
             } else {
                 cg.Emitter.LoadInteger(0);
             }
         }
     }
     cg.Emitter.Return();
 }