Exemple #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"));
        }
Exemple #2
0
 private static ErlangValue OperationWithBooleans(ErlangValue a, ErlangValue b, Func <bool, bool, bool> operation)
 {
     if (!(ErlangAtom.IsTrue(a) || ErlangAtom.IsFalse(a)) || !(ErlangAtom.IsTrue(b) || ErlangAtom.IsFalse(b)))
     {
         return(new ErlangError("not numbers"));
     }
     return(operation(ErlangAtom.IsTrue(a), ErlangAtom.IsTrue(b)) ? ErlangAtom.True : ErlangAtom.False);
 }
Exemple #3
0
 public static ErlangValue Not(ErlangValue value)
 {
     if (ErlangAtom.IsTrue(value))
     {
         return(ErlangAtom.False);
     }
     else if (ErlangAtom.IsFalse(value))
     {
         return(ErlangAtom.True);
     }
     else
     {
         return(new ErlangError("not a boolean"));
     }
 }
Exemple #4
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);
        }
Exemple #5
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);
        }
Exemple #6
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");
                }
            }
        }