Example #1
0
 /// <summary>
 /// Emit this code to load a null value to 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");
     }
     cg.Emitter.LoadNull();
     return Type;
 }
Example #2
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 #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>
        /// 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 #5
0
 /// <summary>
 /// Emit this code to load the value to 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");
     }
     switch (ID) {
         case ParseID.ADD:       return GenerateAdd(cg);
         case ParseID.EQV:       return GenerateEq(cg);
         case ParseID.NEQV:      return GenerateNe(cg);
         case ParseID.XOR:       return GenerateXor(cg);
         case ParseID.OR:        return GenerateOr(cg);
         case ParseID.AND:       return GenerateAnd(cg);
         case ParseID.GT:        return GenerateGt(cg);
         case ParseID.GE:        return GenerateGe(cg);
         case ParseID.LE:        return GenerateLe(cg);
         case ParseID.EQ:        return GenerateEq(cg);
         case ParseID.NE:        return GenerateNe(cg);
         case ParseID.LT:        return GenerateLt(cg);
         case ParseID.SUB:       return GenerateSub(cg);
         case ParseID.MULT:      return GenerateMult(cg);
         case ParseID.DIVIDE:    return GenerateDivide(cg);
         case ParseID.CONCAT:    return GenerateConcat(cg);
         case ParseID.EXP:       return GenerateExp(cg);
     }
     Debug.Assert(false, "Unsupported parse ID for BinaryOpParseNode");
     return Value.Type;
 }
Example #6
0
 /// <summary>
 /// Emit this code to load the value to 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");
     }
     cg.GenerateLoad(Value);
     return Value.Type;
 }
Example #7
0
        /// <summary>
        /// Generate the code to push the specified parameters onto the caller
        /// stack. Unless the called function or subroutine is being called
        /// indirectly (and thus we may not have knowledge of its parameter
        /// count or types), the number of parameters in the caller and callee
        /// must agree.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <returns>A list of system types corresponding to the computed parameters.</returns>
        public new Type[] Generate(CodeGenerator cg)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }

            _locals = new Temporaries(cg.Emitter);

            Type [] paramTypes = new Type[Nodes.Count];
            for (int c = 0; c < Nodes.Count; ++c) {
                ParameterParseNode paramNode = Nodes[c];
                paramTypes[c] = paramNode.Generate(cg, _locals);
            }
            return paramTypes;
        }
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 binary subtraction operator
 SymType GenerateSub(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Left);
     cg.GenerateExpression(Type, Right);
     cg.Emitter.Sub(Type);
     return Type;
 }
Example #10
0
 /// <summary>
 /// Implements the base code generator for the node to invoke a
 /// function implementation with a parse node value.
 /// </summary>
 /// <param name="cg">The code generator object</param>
 /// <param name="node">A parse node supplied to the generator function</param>
 /// <returns>The computed type</returns>
 public virtual void Generate(CodeGenerator cg, ParseNode node)
 {
     throw new InvalidOperationException("ParseNode does not implement Generate");
 }
Example #11
0
 /// <summary>
 /// Emit this code to load the value to 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");
     }
     if (ID == ParseID.LABEL) {
         if (Symbol.IsFixedStatic) {
             cg.Emitter.LoadString(Symbol.Value.StringValue);
             return Type;
         }
         return cg.LoadLocal(Symbol);
     }
     Debug.Assert(false, "Unsupported parse ID for SymbolParseNode");
     return Value.Type;
 }
Example #12
0
 /// <summary>
 /// Implements the base code generator for the node to invoke a
 /// function implementation with a symbol type.
 /// </summary>
 /// <param name="cg">The code generator object</param>
 /// <param name="returnType">The expected type of the return value</param>
 /// <returns>The computed type</returns>
 public override SymType Generate(CodeGenerator cg, SymType returnType)
 {
     if (cg == null) {
         throw new ArgumentNullException("cg");
     }
     cg.Emitter.LoadLocal(_local);
     return Symbol.SystemTypeToSymbolType(_local.Type);
 }
Example #13
0
 /// <summary>
 /// Implements the base code generator for the node to invoke a
 /// function implementation with a symbol type.
 /// </summary>
 /// <param name="cg">The code generator object</param>
 /// <param name="returnType">The expected type of the return value</param>
 /// <returns>The computed type</returns>
 public virtual SymType Generate(CodeGenerator cg, SymType returnType)
 {
     throw new InvalidOperationException("ParseNode does not implement Generate");
 }
Example #14
0
        /// <summary>
        /// Emit the code to call an external function complete with
        /// parameters.
        /// </summary>
        /// <param name="cg">A code generator object</param>
        /// <param name="returnType">The expected return type</param>
        /// <returns>The actual return type from the function</returns>
        public override SymType Generate(CodeGenerator cg, SymType returnType)
        {
            System.Type argType = typeof(void);
            System.Type [] paramTypes;

            if (Parameters != null) {
                paramTypes = Parameters.Generate(cg);
                if (paramTypes.Length > 0) {
                    argType = paramTypes[0];
                }
            } else {
                paramTypes = System.Type.EmptyTypes;
            }

            // For anything else, we emit the appropriate call to the library. If
            // inline is permitted, we check the library for an inline version of the
            // name and if one exists, invoke it to insert the inline code.
            MethodInfo meth;
            if (Inline) {

                // First try specific methods where different inline methods are
                // provided depending on the type.
                meth = typeof(Inlined).GetMethod(Name, new [] { typeof(Emitter), typeof(System.Type) });
                if (meth != null) {
                    object [] ilParams = { cg.Emitter, argType };
                    meth.Invoke(null, ilParams);
                    return Type;
                }

                // Otherwise try the type-less variant.
                meth = typeof(Inlined).GetMethod(Name, new [] { typeof(Emitter) });
                if (meth != null) {
                    object [] ilParams = { cg.Emitter };
                    meth.Invoke(null, ilParams);
                    return Type;
                }
            }

            meth = cg.GetMethodForType(LibraryName, Name, paramTypes);
            cg.Emitter.Call(meth);

            // If this method returns a value but we're invoking it as a
            // subroutine, discard the return value from the stack
            if (returnType == SymType.NONE && meth.ReturnType != typeof(void)) {
                cg.Emitter.Pop();
            }
            returnType = Symbol.SystemTypeToSymbolType(meth.ReturnType);
            if (Parameters != null) {
                Parameters.FreeLocalDescriptors();
            }
            return returnType;
        }
Example #15
0
 /// <summary>
 /// Emit the code to call an external function complete with
 /// parameters.
 /// </summary>
 /// <param name="cg">A code generator object</param>
 public override void Generate(CodeGenerator cg)
 {
     Generate(cg, SymType.NONE);
 }
Example #16
0
        /// <summary>
        /// Generate the code to push the specified parameters onto the caller
        /// stack. Unless the called function or subroutine is being called
        /// indirectly (and thus we may not have knowledge of its parameter
        /// count or types), the number of parameters in the caller and callee
        /// must agree.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="sym">Symbol entry for the called function</param>
        /// <returns>A list of system types corresponding to the computed parameters.</returns>
        public Type[] Generate(CodeGenerator cg, Symbol sym)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (sym == null) {
                throw new ArgumentNullException("sym");
            }

            int callerParameterCount = Nodes.Count;
            int calleeParameterCount = (sym.Parameters != null) ? sym.Parameters.Count : 0;

            if (!sym.IsParameter && callerParameterCount != calleeParameterCount) {
                cg.Error(String.Format("Parameter count mismatch for {0}", sym.Name));
            }

            _locals = new Temporaries(cg.Emitter);

            Type [] paramTypes = new Type[callerParameterCount];
            for (int c = 0; c < Nodes.Count; ++c) {
                ParameterParseNode paramNode = Nodes[c];
                Symbol symParam = (sym.Parameters != null) ? sym.Parameters[c] : null;
                paramTypes[c] = paramNode.Generate(cg, symParam, _locals);
            }
            return paramTypes;
        }
Example #17
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 #18
0
 // Generate the code for a unary minus operator
 SymType GenerateMinus(CodeGenerator cg)
 {
     cg.GenerateExpression(Type, Operand);
     cg.Emitter.Neg(Type);
     return Type;
 }
Example #19
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 #20
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 #21
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 #22
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 #23
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 #24
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 #25
0
 /// <summary>
 /// Emit this code to load the value to 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");
     }
     switch (ID) {
         case ParseID.MINUS:     return GenerateMinus(cg);
         case ParseID.NOT:       return GenerateNot(cg);
     }
     Debug.Assert(false, "Unsupported parse ID for UnaryOpParseNode");
     return Value.Type;
 }
Example #26
0
        // Emit the code that loads part of an entire array by making a copy of
        // the array to the destination array dimensions and copying from the
        // given offset.
        void GenerateLoadSubArray(CodeGenerator cg, IdentifierParseNode identNode, Symbol symParam, Temporaries locals)
        {
            if (!identNode.HasIndexes) {
                cg.GenerateLoadArray(identNode, false);
                return;
            }

            LocalDescriptor index = locals.New(symParam.SystemType);

            cg.GenerateLoadArrayAddress(identNode);
            cg.Emitter.CreateSimpleArray(symParam.ArraySize, Symbol.SymTypeToSystemType(symParam.Type));
            cg.Emitter.Dup();
            cg.Emitter.StoreLocal(index);
            cg.Emitter.LoadInteger(0);
            cg.Emitter.LoadInteger(symParam.ArraySize);
            cg.Emitter.Call(typeof(Array).GetMethod("Copy", new [] { typeof(Array), typeof(int), typeof(Array), typeof(int), typeof(int) }));
            cg.Emitter.LoadLocal(index);
        }
Example #27
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 #28
0
 /// <summary>
 /// Convert the parse tree to executable code and then execute the
 /// resulting code. The return value from the specified entry point function
 /// is returned as an object.
 /// </summary>
 /// <param name="entryPointName">The name of the method to be called</param>
 /// <returns>An ExecutionResult object representing the result of the execution</returns>
 public ExecutionResult Execute(string entryPointName)
 {
     CodeGenerator codegen = new CodeGenerator(_opts);
     MarkExecutable();
     codegen.GenerateCode(_programDef);
     return codegen.Run(entryPointName);
 }
Example #29
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 #30
0
 /// <summary>
 /// Convert the parse tree to executable code then save it to the
 /// filename specified in the options.
 /// </summary>
 public void Save()
 {
     try {
         CodeGenerator codegen = new CodeGenerator(_opts);
         MarkExecutable();
         codegen.GenerateCode(_programDef);
         codegen.Save();
     } catch (CodeGeneratorException e) {
         _messages.Error(e.Filename, MessageCode.CODEGEN, e.Linenumber, e.Message);
     }
 }