Esempio n. 1
0
        public static FunctionDeclaration AddHardwiredFunction(
            string name,
            Module module,
            TypeDefinition returnType,
            params string[] parameters)
        {
            var res = new FunctionDeclaration(name, returnType, new Block(module.Block, module), parameters)
            {
                IsInternal = true
            };

            return(res);
        }
Esempio n. 2
0
        /// <summary>
        ///     Create a score to create a best fit for a function given a parameter list.
        /// </summary>
        /// <param name="func">The function to check the parameters for</param>
        /// <param name="parameters">The list of parameters</param>
        /// <returns>A score (see remarks). In case of -1 no match is possible (see cases in code)</returns>
        /// <remarks>
        ///     How the score is calculated:
        ///     * Start with a score of 0
        ///     * For each parameter
        ///     ** If IsVar and types match exactly --> +1000 (super match)
        ///     ** If ByValue and types match exactly --> + 1000 (only checked for simple types)
        ///     ** If ByValue and types are compatible (e.g. INTEGER can be assigned to REAL) --> +1
        ///     In the unlikely event of having more than 1000 parameters, this algorithm might fail.
        /// </remarks>
        private static int GenerateFunctionParameterScore(FunctionDeclaration func,
                                                          IReadOnlyList <CallParameter> parameters)
        {
            int paramNo    = 0;
            int score      = 0;
            var procParams = func.Block.Declarations.OfType <ProcedureParameterDeclaration>().ToArray();

            if (parameters.Count != procParams.Length)
            {
                return(-1); // will never match
            }

            foreach (var procedureParameter in procParams)
            {
                if (procedureParameter.IsVar)
                {
                    if (!GenerateVarParameterCount(parameters[paramNo], procedureParameter, ref score))
                    {
                        return(-1);
                    }
                }
                else if (procedureParameter.Type.Type.HasFlag(BaseTypes.Simple) &&
                         procedureParameter.Type.Name == parameters[paramNo].TypeName)
                {
                    score += 1000;
                }
                else if (!procedureParameter.Type.IsAssignable(parameters[paramNo].TargetType))
                {
                    return(-1);
                }
                else
                {
                    score++; // match as assignable --> small increment
                }

                paramNo++;
            }

            return(score);
        }
Esempio n. 3
0
        private void DeclareStandardFunctions()
        {
            foreach (var function in _hardwiredFunctions)
            {
                Block.Procedures.Add(FunctionDeclaration.AddHardwiredFunction(function.Name, this,
                                                                              function.Type == null ? SimpleTypeDefinition.VoidType : Block.LookupType(function.Type),
                                                                              function.ParameterTypes));
            }

            Assembly asm = null;

            var sysAsm = Assembly.Load("Oberon0.System");

            asm = sysAsm; // reached only if no exception

            foreach (var type in asm.GetExportedTypes())
            {
                if (type.GetCustomAttribute <Oberon0LibraryAttribute>() != null)
                {
                    LoadLibraryMembers(type);
                }
            }
        }
Esempio n. 4
0
#pragma warning disable CS3001 // Argument type is not CLS-compliant
        private FunctionDeclaration LookupFunction(string procedureName, IToken token,
                                                   IReadOnlyList <CallParameter> callParameters)
#pragma warning restore CS3001 // Argument type is not CLS-compliant
        {
            var b = this;
            FunctionDeclaration resFunc = null;
            // try to find the function with the best match (score) (e.g. ABS(REAL) and ABS(INTEGER) share the same function name
            // of not found on current block level, move up (until root) to find something appropriate.
            int score = -1;

            while (b != null)
            {
                var res = b.Procedures.Where(x => x.Name == procedureName);
                foreach (var func in res)
                {
                    int newScore = GenerateFunctionParameterScore(func, callParameters);

                    if (newScore <= score)
                    {
                        continue;
                    }

                    resFunc = func;
                    score   = newScore;
                }

                if (score >= 0)
                {
                    break; // found
                }

                b = b.Parent;
            }

            if (resFunc == null)
            {
                var parameterList = new List <ProcedureParameterDeclaration>(callParameters.Count);
                int n             = 0;

                parameterList.AddRange(
                    callParameters.Select(
                        expression =>
                        new ProcedureParameterDeclaration("param_" + n++, this, expression.TargetType, false)));

                string prototype = FunctionDeclaration.BuildPrototype(
                    procedureName,
                    SimpleTypeDefinition.VoidType,
                    parameterList.ToArray());
                if (Module.CompilerInstance != null)
                {
                    Module.CompilerInstance.Parser.NotifyErrorListeners(
                        token,
                        $"No procedure/function with prototype '{prototype}' found",
                        null);
                }
                else
                {
                    throw new InvalidOperationException($"No procedure/function with prototype '{prototype}' found");
                }
            }

            return(resFunc);
        }