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")); }
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); }
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")); } }
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); }
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); }
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"); } } }