Пример #1
0
        protected override ErlangValue EvaluateLocal(ErlangProcess process, string functionName, ErlangValue[] parameters)
        {
            var function = GetFunction(functionName, parameters.Length);

            if (function == null)
            {
                return(new ErlangError("no matching function found"));
            }

            if (!function.IsPublic)
            {
                return(new ErlangError("no matching function found"));
            }

            var overload = function.GetFunctionOverload(process, parameters);

            if (overload != null)
            {
                return(overload.Evaluate(process));
            }
            else
            {
                return(new ErlangError("no matching function found"));
            }
        }
Пример #2
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            ErlangValue result     = null;
            bool        evaluated  = false;
            var         parameters = Parameters.Select(p => p.Evaluate(process)).ToArray();

            if (Module == null)
            {
                var module = GetModule();
                if (module != null)
                {
                    // try to execute from the current module
                    if (module.FunctionExistsInternal(Function, parameters.Length))
                    {
                        result    = module.EvaluateInternal(process, Function, parameters);
                        evaluated = true;
                    }
                }
            }

            if (!evaluated)
            {
                // couldn't execute from this module, kick it back to the ErlangProcess to find the function
                result = process.Evaluate(Module, Function, parameters);
            }

            return(result);
        }
Пример #3
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            var value = Expression.Evaluate(process);

            if (value.Kind == ErlangValueKind.Error)
            {
                return(value);
            }
            foreach (var branch in Branches)
            {
                process.CallStack.CurrentFrame.IncreaseScopeLevel();
                if (ErlangBinder.TryBindParameter(branch.Pattern, value, process.CallStack.CurrentFrame))
                {
                    if (branch.Guard == null || ErlangAtom.IsTrue(branch.Guard.Evaluate(process)))
                    {
                        var result = branch.Evaluate(process);
                        process.CallStack.CurrentFrame.DecreaseScopeLevel();
                        return(result);
                    }
                }
                process.CallStack.CurrentFrame.DecreaseScopeLevel();
            }

            return(new ErlangError("bad match on case"));
        }
Пример #4
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            var result = Expression.Evaluate(process);

            if (result.Kind == ErlangValueKind.Error)
            {
                return(result);
            }
            switch (Operator)
            {
            case ErlangOperatorKind.Plus:
                return(ErlangValue.Multiply(result, ErlangNumber.One));

            case ErlangOperatorKind.Minus:
                return(ErlangValue.Multiply(result, ErlangNumber.NegativeOne));

            case ErlangOperatorKind.Not:
                return(ErlangValue.Not(result));

            case ErlangOperatorKind.BNot:
                if (result.Kind == ErlangValueKind.Number)
                {
                    return(ErlangNumber.BNot((ErlangNumber)result));
                }
                else
                {
                    return(new ErlangError("not integral"));
                }

            default:
                return(new ErlangError(string.Format("Invalid unary operator: {0}", Operator)));
            }
        }
Пример #5
0
        public ErlangValue Evaluate(ErlangProcess process, string functionName, ErlangValue[] parameters)
        {
            ErlangValue error = null;

            if (functionName == "module_info")
            {
                if (parameters.Length == 0)
                {
                    return(ModuleInfo);
                }
                else if (parameters.Length == 1)
                {
                    if (parameters[0].Kind == ErlangValueKind.Atom)
                    {
                        var text = ((ErlangAtom)parameters[0]).Name;
                        if (text == "functions")
                        {
                            return(AllFunctions);
                        }
                        else
                        {
                            // find matching tuple
                            var list = ModuleInfo;
                            while (list != null && list.Value != null)
                            {
                                Debug.Assert(list.Value is ErlangTuple);
                                var tuple = (ErlangTuple)list.Value;
                                Debug.Assert(tuple.Airity == 2);
                                Debug.Assert(tuple.Values[0].Kind == ErlangValueKind.Atom);
                                if (((ErlangAtom)tuple.Values[0]).Name == text)
                                {
                                    Debug.Assert(tuple.Values[1].Kind == ErlangValueKind.List);
                                    return(tuple.Values[1]);
                                }

                                list = list.Tail as ErlangList;
                            }

                            return(new ErlangError("no matching tuple item"));
                        }
                    }
                    else
                    {
                        error = new ErlangError("no matching function");
                    }
                }
                else
                {
                    error = new ErlangError("no matching function");
                }
            }
            error = error ?? parameters.FirstOrDefault(p => p.Kind == ErlangValueKind.Error);
            return(error ?? EvaluateLocal(process, functionName, parameters));
        }
Пример #6
0
        protected override ErlangValue EvaluateLocal(ErlangProcess process, string function, ErlangValue[] parameters)
        {
            MethodInfo methodInfo;

            if (functionMap.TryGetValue(Tuple.Create(function, parameters.Length), out methodInfo))
            {
                return((ErlangValue)methodInfo.Invoke(Target, parameters));
            }

            return(new ErlangError("no matching function found"));
        }
Пример #7
0
 public ErlangReplFunctions(ErlangProcess process)
 {
     this.process = process;
     foreach (var methodInfo in GetType().GetTypeInfo().DeclaredMethods)
     {
         var parameters  = methodInfo.GetParameters();
         var methodAttrs = methodInfo.GetCustomAttributes(typeof(ErlangFunctionAttribute), false).OfType <ErlangFunctionAttribute>().ToArray();
         if (parameters.All(p => p.ParameterType == typeof(ErlangExpression)) &&
             methodInfo.ReturnType == typeof(ErlangValue) &&
             methodAttrs.Length == 1)
         {
             functionMap.Add(Tuple.Create(methodAttrs[0].Name, parameters.Length), methodInfo);
         }
     }
 }
Пример #8
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            var values = new ErlangValue[Elements.Length];

            for (int i = 0; i < Elements.Length; i++)
            {
                var value = Elements[i].Evaluate(process);
                if (value.Kind == ErlangValueKind.Error)
                {
                    return(value);
                }
                values[i] = value;
            }

            return(new ErlangTuple(values));
        }
Пример #9
0
        public ErlangFunctionOverloadExpression GetFunctionOverload(ErlangProcess process, ErlangValue[] parameters)
        {
            Debug.Assert(parameters.Length == Airity);
            for (int i = 0; i < Overloads.Length; i++)
            {
                if (Overloads[i].TryBindParameters(process, parameters))
                {
                    var guard = Overloads[i].Guard;
                    if (guard == null || ErlangAtom.IsTrue(guard.Evaluate(process)))
                    {
                        return(Overloads[i]);
                    }
                }
            }

            return(null);
        }
Пример #10
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            var values = new ErlangValue[Elements.Length];

            for (int i = 0; i < Elements.Length; i++)
            {
                var value = Elements[i].Evaluate(process);
                if (value.Kind == ErlangValueKind.Error)
                {
                    return(value);
                }
                values[i] = value;
            }

            var list = new ErlangList(values, Tail == null ? null : Tail.Evaluate(process));

            return(list);
        }
Пример #11
0
        public static bool TryBindParameters(ErlangProcess process, ErlangExpression[] parameters, ErlangValue[] values)
        {
            if (parameters.Length != values.Length)
            {
                return(false);
            }
            var frame = process.CallStack.CurrentFrame;

            for (int i = 0; i < values.Length; i++)
            {
                if (!ErlangBinder.TryBindParameter(parameters[i], values[i], frame, true))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #12
0
        internal ErlangValue EvaluateInternal(ErlangProcess process, string functionName, ErlangValue[] parameters)
        {
            ErlangValue result;
            var         function = GetFunction(functionName, parameters.Length);

            process.CallStack.Push(new ErlangStackFrame(Name, functionName, parameters.Length));
            var overload = function.GetFunctionOverload(process, parameters);

            if (overload != null)
            {
                result = overload.Evaluate(process);
            }
            else
            {
                result = new ErlangError("no matching function found");
            }

            process.CallStack.Pop();
            return(result);
        }
Пример #13
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            Debug.Assert(Clauses.Length > 0);
            var isAnd  = Clauses[0].IsAnd;
            var result = ErlangAtom.IsTrue(Clauses[0].Evaluate(process));

            for (int i = 1; i < Clauses.Length; i++)
            {
                var next = Clauses[i].Evaluate(process);
                if (isAnd)
                {
                    result = result && ErlangAtom.IsTrue(Clauses[i].Evaluate(process));
                }
                else
                {
                    result = result || ErlangAtom.IsTrue(Clauses[i].Evaluate(process));
                }

                isAnd = Clauses[i].IsAnd;
            }

            return(result ? ErlangAtom.True : ErlangAtom.False);
        }
Пример #14
0
 public bool TryBindParameters(ErlangProcess process, ErlangValue[] values)
 {
     return(TryBindParameters(process, Parameters, values));
 }
Пример #15
0
 protected abstract ErlangValue EvaluateLocal(ErlangProcess process, string functionName, ErlangValue[] parameters);
Пример #16
0
 public ErlangBifs(ErlangProcess process)
 {
     Process = process;
 }
Пример #17
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            // variable assignment or pattern match
            if (Operator == ErlangOperatorKind.Equals)
            {
                // first evaluate the right side
                var right = Right.Evaluate(process);
                if (right.Kind == ErlangValueKind.Error)
                {
                    return(right);
                }

                // now match to the left
                if (ErlangBinder.TryBindParameter(Left, right, process.CallStack.CurrentFrame))
                {
                    return(right);
                }
                else
                {
                    return(new ErlangError("bad match"));
                }
            }

            var left = Left.Evaluate(process);

            if (left.Kind == ErlangValueKind.Error)
            {
                return(left);
            }
            if (IsShortCircuitOperator(Operator))
            {
                switch (Operator)
                {
                case ErlangOperatorKind.AndAlso:
                    if (ErlangAtom.IsTrue(left))
                    {
                        return(Right.Evaluate(process));
                    }
                    else
                    {
                        return(ErlangAtom.False);
                    }

                case ErlangOperatorKind.OrElse:
                    if (ErlangAtom.IsTrue(left))
                    {
                        return(left);
                    }
                    else
                    {
                        return(Right.Evaluate(process));
                    }

                default:
                    throw new ArgumentException("invalid operator");
                }
            }
            else
            {
                var right = Right.Evaluate(process);
                if (right.Kind == ErlangValueKind.Error)
                {
                    return(right);
                }
                switch (Operator)
                {
                case ErlangOperatorKind.Plus:
                    return(ErlangValue.Add(left, right));

                case ErlangOperatorKind.Minus:
                    return(ErlangValue.Subtract(left, right));

                case ErlangOperatorKind.Asterisk:
                    return(ErlangValue.Multiply(left, right));

                case ErlangOperatorKind.Slash:
                    return(ErlangValue.Divide(left, right));

                case ErlangOperatorKind.And:
                    return(ErlangValue.And(left, right));

                case ErlangOperatorKind.Or:
                    return(ErlangValue.Or(left, right));

                case ErlangOperatorKind.Less:
                    return(ErlangValue.Less(left, right));

                case ErlangOperatorKind.EqualsLess:
                    return(ErlangValue.LessEquals(left, right));

                case ErlangOperatorKind.Greater:
                    return(ErlangValue.Greater(left, right));

                case ErlangOperatorKind.GreaterEquals:
                    return(ErlangValue.GreaterEquals(left, right));

                case ErlangOperatorKind.EqualsEquals:
                    return(ErlangValue.EqualsEquals(left, right));

                case ErlangOperatorKind.SlashEquals:
                    return(ErlangValue.SlashEquals(left, right));

                case ErlangOperatorKind.EqualsColonEquals:
                    return(ErlangValue.EqualsColonEquals(left, right));

                case ErlangOperatorKind.EqualsSlashEquals:
                    return(ErlangValue.EqualsSlashEquals(left, right));

                case ErlangOperatorKind.PlusPlus:
                    return(ErlangValue.PlusPlus(left, right));

                default:
                    throw new ArgumentException("invalid operator");
                }
            }
        }
Пример #18
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            var value = process.CallStack.CurrentFrame.GetVariable(Variable);

            return(value ?? new ErlangError(string.Format("No such variable {0}", Variable)));
        }
Пример #19
0
 public override ErlangValue Evaluate(ErlangProcess process)
 {
     return(Evaluate());
 }
Пример #20
0
 public override ErlangValue Evaluate(ErlangProcess process)
 {
     return(Expression.Evaluate(process));
 }
Пример #21
0
 public ErlangExpressionEvaluator()
 {
     Process = new ErlangProcess();
 }
Пример #22
0
 public virtual ErlangValue Evaluate(ErlangProcess process)
 {
     throw new NotSupportedException();
 }
Пример #23
0
        public override ErlangValue Evaluate(ErlangProcess process)
        {
            ErlangValue last = null;
            ErlangExpressionBlockExpression def    = this;
            ErlangCompiledModule            module = GetModule();
            var  children   = def.GetChildren();
            bool doTailCall = false;

            do
            {
                doTailCall = false; // ensure we're reset from the last loop
                // evaluate each expression
                Debug.Assert(children.Length > 0);
                for (int i = 0; !doTailCall && i < children.Length; i++)
                {
                    var    expression = children[i];
                    string moduleName = null;
                    ErlangFunctionInvocationExpression function = null;
                    ErlangStackFrame tailCallCandidate          = null;
                    if (UseTailCalls && i == children.Length - 1 && expression is ErlangFunctionInvocationExpression && expression.IsLastChild)
                    {
                        // if last expression and it's a function invocation
                        function          = (ErlangFunctionInvocationExpression)expression;
                        moduleName        = function.Module ?? module.Name;
                        tailCallCandidate = process.CallStack.GetTailCallCandidate(
                            moduleName,
                            function.Function,
                            function.Parameters.Length);
                        doTailCall = tailCallCandidate != null;
                    }

                    if (doTailCall)
                    {
                        // evaluate parameters
                        var evaledParams = new ErlangValue[function.Parameters.Length];
                        for (int j = 0; j < function.Parameters.Length; j++)
                        {
                            var value = function.Parameters[j].Evaluate(process);
                            if (value.Kind == ErlangValueKind.Error)
                            {
                                return(value);
                            }
                            evaledParams[j] = value;
                        }

                        // prepare new frame
                        var newFrame = new ErlangStackFrame(tailCallCandidate.Module,
                                                            tailCallCandidate.Function,
                                                            tailCallCandidate.Airity);
                        process.CallStack.RewindForTailCall(newFrame);

                        // find the new definition
                        var group = module.GetFunction(function.Function, evaledParams.Length);
                        def = group.GetFunctionOverload(process, evaledParams);
                        if (def == null)
                        {
                            return(new ErlangAtom("no_such_tailcall_function"));
                        }
                        children = def.GetChildren();
                    }
                    else
                    {
                        // not a tailcall, just invoke normally
                        last = children[i].Evaluate(process);
                        if (last.Kind == ErlangValueKind.Error)
                        {
                            return(last); // decrease scope?
                        }
                    }
                }
            } while (doTailCall);

            return(last);
        }