Beispiel #1
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"));
        }
Beispiel #2
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);
        }
Beispiel #3
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");
                }
            }
        }