public FuncCodeRec(
            string FuncName,
            SymbolListRec Parameters,
            PcodeRec PcodeThing,
            DataTypes ReturnType,
            string Filename)
        {
            this.FunctionName = FuncName;

            this.NumParameters     = SymbolListRec.GetLength(Parameters);
            this.ParameterTypeList = new DataTypes[this.NumParameters];

            this.Filename = Filename;

            SymbolListRec FormalParameterScanner = Parameters;
            int           ParamIndex             = 0;

            while (FormalParameterScanner != null)
            {
                this.ParameterTypeList[ParamIndex] = FormalParameterScanner.First.VariableDataType;
                FormalParameterScanner             = FormalParameterScanner.Rest;
                ParamIndex++;
            }

            this.Code = PcodeThing;

            this.ReturnType = ReturnType;
        }
Exemple #2
0
        public static int GetLength(SymbolListRec node) // null ok
        {
            int c = 0;

            while (node != null)
            {
                c++;
                node = node.rest;
            }
            return(c);
        }
Exemple #3
0
 // this version permits redeclaration
 public void SymbolBecomeFunction2(SymbolListRec ArgList, DataTypes ReturnType)
 {
     if ((kind != SymbolKind.Undefined) && (kind != SymbolKind.Function))
     {
         // already defined
         Debug.Assert(false);
         throw new InvalidOperationException();
     }
     kind            = SymbolKind.Function;
     objectDataType  = ReturnType;
     functionArgList = ArgList;
 }
        private static void SymbolicArgListToType(
            SymbolRec functionSymbol,
            out DataTypes[] argsTypesOut,
            out string[] argsNamesOut)
        {
            List <DataTypes> argsTypes = new List <DataTypes>();
            List <string>    argsNames = new List <string>();
            SymbolListRec    argNode   = functionSymbol.FunctionArgList;

            while (argNode != null)
            {
                SymbolRec arg = argNode.First;
                argsTypes.Add(arg.VariableDataType);
                argsNames.Add(arg.SymbolName);
                argNode = argNode.Rest;
            }
            argsTypesOut = argsTypes.ToArray();
            argsNamesOut = argsNames.ToArray();
        }
        private static SymbolRec ArgListTypesToSymbol(
            string functionName,
            DataTypes[] argsTypes,
            DataTypes returnType)
        {
            SymbolListRec head = null;

            for (int i = argsTypes.Length - 1; i >= 0; i--)
            {
                SymbolRec symbolArg = new SymbolRec(null);
                symbolArg.SymbolBecomeVariable(argsTypes[i]);
                SymbolListRec node = new SymbolListRec(symbolArg, head);
                head = node;
            }

            SymbolRec symbol = new SymbolRec(functionName);

            symbol.SymbolBecomeFunction(head, returnType);
            return(symbol);
        }
        // Compile multiple modules. (eliminates the need to do prototyping or function signature inference.)
        // CodeCenter is cleared, and if compilation succeeds, the functions are added to CodeCenter.
        public static CompileErrors CompileWholeProgram(
            out int ErrorLineNumber,
            out int ErrorModuleIndex,
            string[] TextDatas,
            object[] Signatures,
            CodeCenterRec CodeCenter,
            string[] Filenames)
        {
            Debug.Assert(TextDatas.Length == Signatures.Length);
            Debug.Assert(TextDatas.Length == Filenames.Length);

            ErrorLineNumber  = -1;
            ErrorModuleIndex = -1;

            CodeCenter.FlushAllCompiledFunctions();
            CodeCenter.RetainedFunctionSignatures = new KeyValuePair <string, FunctionSignature> [0];

            // parse

            List <SymbolRec>     SymbolTableEntriesForForm = new List <SymbolRec>();
            List <ASTExpression> FunctionBodyRecords       = new List <ASTExpression>();
            List <int>           ModuleIndices             = new List <int>();
            Dictionary <string, List <ParserContext.FunctionSymbolRefInfo> > FunctionRefSymbolList = new Dictionary <string, List <ParserContext.FunctionSymbolRefInfo> >();
            List <int> InitialLineNumbersOfForm = new List <int>();

            for (int module = 0; module < TextDatas.Length; module++)
            {
                string TextData = TextDatas[module];

                ErrorModuleIndex = module;

                ScannerRec <KeywordsType> TheScanner     = new ScannerRec <KeywordsType>(TextData, KeywordTable);
                SymbolTableRec            TheSymbolTable = new SymbolTableRec();

                /* loop until there are no more things to parse */
                while (true)
                {
                    TokenRec <KeywordsType> Token = TheScanner.GetNextToken();
                    int InitialLineNumberOfForm   = TheScanner.GetCurrentLineNumber();
                    if (Token.GetTokenType() == TokenTypes.eTokenEndOfInput)
                    {
                        /* no more functions to parse, so stop */
                        break;
                    }

                    SymbolRec     SymbolTableEntryForForm;
                    ASTExpression FunctionBodyRecord;

                    /* parse the function */
                    TheScanner.UngetToken(Token);
                    CompileErrors Error = ParseForm(
                        out SymbolTableEntryForForm,
                        out FunctionBodyRecord,
                        new ParserContext(
                            TheScanner,
                            TheSymbolTable,
                            FunctionRefSymbolList),
                        out ErrorLineNumber);
                    if (Error != CompileErrors.eCompileNoError)
                    {
                        return(Error);
                    }

                    Debug.Assert(FunctionBodyRecord != null);
                    ModuleIndices.Add(module);
                    SymbolTableEntriesForForm.Add(SymbolTableEntryForForm);
                    FunctionBodyRecords.Add(FunctionBodyRecord);
                    InitialLineNumbersOfForm.Add(InitialLineNumberOfForm);
                }

                foreach (KeyValuePair <string, List <ParserContext.FunctionSymbolRefInfo> > name in FunctionRefSymbolList)
                {
                    foreach (ParserContext.FunctionSymbolRefInfo funcRef in name.Value)
                    {
                        funcRef.module = module;
                    }
                }
            }

            // push function type signatures into function call refs

            Dictionary <string, bool> functionNamesUsed = new Dictionary <string, bool>();

            for (int i = 0; i < SymbolTableEntriesForForm.Count; i++)
            {
                ErrorModuleIndex = ModuleIndices[i];

                SymbolRec FunctionDeclarationSymbol = SymbolTableEntriesForForm[i];
                if (functionNamesUsed.ContainsKey(FunctionDeclarationSymbol.SymbolName))
                {
                    ErrorLineNumber = FunctionBodyRecords[i].LineNumber;
                    return(CompileErrors.eCompileMultiplyDeclaredFunction);
                }
                functionNamesUsed.Add(FunctionDeclarationSymbol.SymbolName, false);

                List <ParserContext.FunctionSymbolRefInfo> symbols;
                if (FunctionRefSymbolList.TryGetValue(FunctionDeclarationSymbol.SymbolName, out symbols))
                {
                    foreach (ParserContext.FunctionSymbolRefInfo functionRef in symbols)
                    {
                        functionRef.symbol.SymbolBecomeFunction2(
                            FunctionDeclarationSymbol.FunctionArgList,
                            FunctionDeclarationSymbol.FunctionReturnType);
                    }
                    FunctionRefSymbolList.Remove(FunctionDeclarationSymbol.SymbolName);
                }
            }

            foreach (KeyValuePair <string, List <ParserContext.FunctionSymbolRefInfo> > name in FunctionRefSymbolList)
            {
                foreach (ParserContext.FunctionSymbolRefInfo funcRef in name.Value)
                {
                    ErrorModuleIndex = funcRef.module;
                    ErrorLineNumber  = funcRef.lineNumber;
                    return(CompileErrors.eCompileMultiplyDeclaredFunction);
                }
            }

            // type check and type inference

            for (int i = 0; i < FunctionBodyRecords.Count; i++)
            {
                int           module = ModuleIndices[i];
                SymbolRec     SymbolTableEntryForForm = SymbolTableEntriesForForm[i];
                ASTExpression FunctionBodyRecord      = FunctionBodyRecords[i];
                int           InitialLineNumberOfForm = InitialLineNumbersOfForm[i];

                ErrorModuleIndex = module;

                /* SymbolTableEntryForForm will be the symbol table entry that */
                /* was added to the symbol table.  FunctionBodyRecord is either */
                /* an expression for a function or NIL if it was a prototype */

                Debug.Assert(!CodeCenter.CodeCenterHaveThisFunction(SymbolTableEntryForForm.SymbolName));

                /* step 1:  do type checking */
                DataTypes     ResultingType;
                CompileErrors Error = FunctionBodyRecord.TypeCheck(
                    out ResultingType,
                    out ErrorLineNumber);
                if (Error != CompileErrors.eCompileNoError)
                {
                    return(Error);
                }
                /* check to see that resulting type matches declared type */
                if (!CanRightBeMadeToMatchLeft(SymbolTableEntryForForm.FunctionReturnType, ResultingType))
                {
                    ErrorLineNumber = InitialLineNumberOfForm;
                    return(CompileErrors.eCompileTypeMismatch);
                }
                /* if it has to be promoted, then promote it */
                if (MustRightBePromotedToLeft(SymbolTableEntryForForm.FunctionReturnType, ResultingType))
                {
                    /* insert promotion operator above expression */
                    ASTExpression ReplacementExpr = PromoteTheExpression(
                        ResultingType,
                        SymbolTableEntryForForm.FunctionReturnType,
                        FunctionBodyRecord,
                        InitialLineNumberOfForm);
                    FunctionBodyRecord = ReplacementExpr;
                    /* sanity check */
                    Error = FunctionBodyRecord.TypeCheck(
                        out ResultingType,
                        out ErrorLineNumber);
                    if (Error != CompileErrors.eCompileNoError)
                    {
                        // type promotion caused failure
                        Debug.Assert(false);
                        throw new InvalidOperationException();
                    }
                    if (ResultingType != SymbolTableEntryForForm.FunctionReturnType)
                    {
                        // after type promotion, types are no longer the same
                        Debug.Assert(false);
                        throw new InvalidOperationException();
                    }
                }
            }

            // code generation

            CILAssembly cilAssembly = null;

            if (CILObject.EnableCIL)
            {
                cilAssembly = new CILAssembly();
            }

            FuncCodeRec[] TheWholeFunctionThings = new FuncCodeRec[FunctionBodyRecords.Count];
            for (int i = 0; i < FunctionBodyRecords.Count; i++)
            {
                int           module = ModuleIndices[i];
                SymbolRec     SymbolTableEntryForForm = SymbolTableEntriesForForm[i];
                ASTExpression FunctionBodyRecord      = FunctionBodyRecords[i];
                int           InitialLineNumberOfForm = InitialLineNumbersOfForm[i];

                string Filename  = Filenames[module];
                object Signature = Signatures[module];

                ErrorModuleIndex = module;

                Debug.Assert(!CodeCenter.CodeCenterHaveThisFunction(SymbolTableEntryForForm.SymbolName));

                /* step 1.5:  optimize the AST */
                OptimizeAST(ref FunctionBodyRecord);

                /* step 2:  do code generation */
                /* calling conventions:  */
                /*  - push the arguments */
                /*  - funccall pushes the return address */
                /* thus, upon entry, Stack[0] will be the return address */
                /* and Stack[-1] will be the rightmost argument */
                /* on return, args and retaddr are popped and retval replaces them */
                int           StackDepth             = 0;
                int           MaxStackDepth          = 0;
                int           ReturnValueLocation    = StackDepth; /* remember return value location */
                int           ArgumentIndex          = 0;
                SymbolListRec FormalArgumentListScan = SymbolTableEntryForForm.FunctionArgList;
                while (FormalArgumentListScan != null)
                {
                    SymbolRec TheFormalArg = FormalArgumentListScan.First;
                    StackDepth++;                                          /* allocate first */
                    MaxStackDepth = Math.Max(MaxStackDepth, StackDepth);
                    TheFormalArg.SymbolVariableStackLocation = StackDepth; /* remember */
                    ArgumentIndex++;
                    FormalArgumentListScan = FormalArgumentListScan.Rest;
                }
                /* reserve return address spot */
                StackDepth++;
                MaxStackDepth = Math.Max(MaxStackDepth, StackDepth);
                /* allocate the function code */
                PcodeRec TheFunctionCode = new PcodeRec();
                FunctionBodyRecord.PcodeGen(
                    TheFunctionCode,
                    ref StackDepth,
                    ref MaxStackDepth);
                Debug.Assert(StackDepth <= MaxStackDepth);
                /* 2 extra words for retaddr and resultofexpr */
                if (StackDepth != ArgumentIndex + 1 + 1)
                {
                    // stack depth error after evaluating function
                    Debug.Assert(false);
                    throw new InvalidOperationException();
                }
                /* now put the return instruction (pops retaddr and args, leaving retval) */
                int ignored;
                TheFunctionCode.AddPcodeInstruction(Pcodes.epReturnFromSubroutine, out ignored, InitialLineNumberOfForm);
                TheFunctionCode.AddPcodeOperandInteger(ArgumentIndex);
                StackDepth = StackDepth - (1 + ArgumentIndex);
                Debug.Assert(StackDepth <= MaxStackDepth);
                if (StackDepth != 1)
                {
                    // stack depth is wrong at end of function
                    Debug.Assert(false);
                    throw new InvalidOperationException();
                }

                TheFunctionCode.MaxStackDepth = MaxStackDepth;

                /* step 2.5:  optimize the code */
                TheFunctionCode.OptimizePcode();

                /* step 3:  create the function and save it away */
                FuncCodeRec TheWholeFunctionThing = new FuncCodeRec(
                    SymbolTableEntryForForm.SymbolName,
                    SymbolTableEntryForForm.FunctionArgList,
                    TheFunctionCode,
                    SymbolTableEntryForForm.FunctionReturnType,
                    Filename);

                TheWholeFunctionThings[i] = TheWholeFunctionThing;

                if (CILObject.EnableCIL)
                {
                    DataTypes[] argsTypes;
                    string[]    argsNames;
                    SymbolicArgListToType(SymbolTableEntryForForm, out argsTypes, out argsNames);
                    CILObject cilObject = new CILObject(
                        CodeCenter.ManagedFunctionLinker,
                        argsTypes,
                        argsNames,
                        SymbolTableEntryForForm.FunctionReturnType,
                        FunctionBodyRecord,
                        cilAssembly,
                        false /*argsByRef*/);
                    TheWholeFunctionThing.CILObject = cilObject;
                }
            }

            // register after entire assembly is emitted
            if (CILObject.EnableCIL)
            {
                cilAssembly.Finish();
            }

            for (int i = 0; i < TheWholeFunctionThings.Length; i++)
            {
                FuncCodeRec TheWholeFunctionThing = TheWholeFunctionThings[i];
                object      Signature             = Signatures[ModuleIndices[i]];

                CodeCenter.AddFunctionToCodeCenter(TheWholeFunctionThing, Signature);
            }

            // retain signatures for compilation of special functions

            CodeCenter.RetainedFunctionSignatures = new KeyValuePair <string, FunctionSignature> [SymbolTableEntriesForForm.Count];
            for (int i = 0; i < CodeCenter.RetainedFunctionSignatures.Length; i++)
            {
                DataTypes[] argsTypes;
                string[]    argsNames;
                SymbolicArgListToType(SymbolTableEntriesForForm[i], out argsTypes, out argsNames);
                CodeCenter.RetainedFunctionSignatures[i] = new KeyValuePair <string, FunctionSignature>(
                    SymbolTableEntriesForForm[i].SymbolName,
                    new FunctionSignature(
                        argsTypes,
                        SymbolTableEntriesForForm[i].FunctionReturnType));
            }

            return(CompileErrors.eCompileNoError);
        }
Exemple #7
0
 public static SymbolListRec Cons(SymbolRec first, SymbolListRec rest)
 {
     return(new SymbolListRec(first, rest));
 }
Exemple #8
0
 public SymbolListRec(SymbolRec first, SymbolListRec rest)
 {
     this.first = first;
     this.rest  = rest;
 }