コード例 #1
0
ファイル: CustomFunction.cs プロジェクト: Esvandiary/Element
        /// <summary>
        /// Compiles a single expression (e.g. part of an expression list)
        /// </summary>
        private IFunction CompileExpression(IFunction?previous, Match exprAst, CompilationStack stack, CompilationContext context)
        {
            switch (exprAst.Name)
            {
            case ElementAST.NumberExpression:
                return(new Constant((float)exprAst.Value));

            case ElementAST.VariableExpression:
                context.Push(MakeCallSite(exprAst));
                var variable = CompileFunction(exprAst.Text, stack, context);
                context.Pop();
                return(variable);

            case ElementAST.SubExpression:
                return(previous.Call(exprAst[ElementAST.SubExpressionName].Text, context, MakeCallSite(exprAst)));

            case ElementAST.CallExpression:
                // This is called a *lot*, so try to make it high performance:
                var args    = exprAst[ElementAST.CallArguments].Matches;
                var argList = new IFunction[args.Count];
                for (var i = 0; i < argList.Length; i++)
                {
                    argList[i] = CompileExpressionList(args[i], stack, context);
                }

                return(previous.Call(argList, context, MakeCallSite(exprAst)));

            default:
                return(context.LogError($"Unknown expression {exprAst}"));
            }
        }
コード例 #2
0
ファイル: CustomFunction.cs プロジェクト: Esvandiary/Element
        public override IFunction CallInternal(IFunction[] arguments, string output, CompilationContext context)
        {
            if (IsNamespace && arguments.Length == 0)
            {
                return(CompileIntermediate(arguments, output, context));
            }
            else if (IsNamespace && !IsClass)
            {
                return(context.LogError($"This is a Namespace, so it has no constructor"));
            }

            if (IsClass &&
                arguments.Length == Inputs.Length &&
                Outputs.All(p => p.Name != output) &&
                NamespaceMembers.Contains(output))
            {
                var memberFunction = CompileIntermediate(Array.Empty <IFunction>(), output, context);
                if (memberFunction.Inputs.Length > 0 && memberFunction.Inputs[0].Name == "this")
                {
                    var classInstance = this.Call(arguments, context);
                    return(classInstance.AsMethod(memberFunction, MakeCallSite(Ast), context));
                }
            }

            context.Push(MakeCallSite(Ast));
            if (this.CheckArguments(arguments, output, context) != null)
            {
                context.Pop();
                return(Error.Instance);
            }

            context.Pop();

            if (IsClass)
            {
                return(arguments[Array.FindIndex(Outputs, p => p.Name == output)]);
            }

            var outputPort = Outputs.First(p => p.Name == output);
            var outValue   = CompileIntermediate(arguments, output, context);
            var success    = outputPort.Type.SatisfiedBy(outValue, context);

            return(success switch
            {
                false => context.LogError("ELE0008", $"Output `{outputPort}` was not satisfied by its value `{outValue}` (See previous errors)"),
                null => Error.Instance,
                _ => outValue
            });
コード例 #3
0
        public static IFunction Call(this IFunction function, IFunction[] arguments, string output,
                                     CompilationContext info, CallSite?callSite = null)
        {
            if (function == null)
            {
                throw new ArgumentNullException(nameof(function));
            }
            if (callSite.HasValue)
            {
                info.Push(callSite.Value);
            }
            var retval = function.CallInternal(arguments, output, info);

            if (callSite.HasValue)
            {
                info.Pop();
            }
            return(retval);
        }