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