public static int Match(Value left, Value right, Namespace ns, bool usePopper = true) { using (var popper = new NamespacePopper(ns, "case match")) { popper.Push(); Runtime.State.SetLocal(Runtime.State.DefaultParameterNames.ValueVariable, left); if (left.ID == right.ID) { return(0); } if (right.Type == ValueType.Any) { return(0); } if (right.Type == ValueType.Placeholder) { Runtime.State.SetLocal(right.Text, left); return(0); } if (right.IsArray && left.IsArray) { var leftArray = (Array)left.SourceArray; var rightArray = (Array)right.SourceArray; int match = leftArray.Match(rightArray); return(match); } var obj1 = left as Object; if (obj1 != null) { var obj2 = right as Object; if (obj2 != null) { var chains = new Hash <string, MessageChain>(); var bindings = new Hash <string, Value> { DefaultValue = "" }; var repeating = false; int comparison; while (true) { comparison = obj1.Compare(obj2, chains, new MessageChain(), bindings, ref repeating); if (comparison == 0) { foreach (KeyValuePair <string, MessageChain> item in chains) { Runtime.State[item.Key, true] = item.Value.Invoke(obj1); } return(comparison); } if (!repeating) { break; } } return(comparison); } var cls = right as Class; if (cls != null) { return(obj1.Class.ClassName.CompareTo(cls.ClassName)); } } var pattern = right as Pattern; if (pattern != null) { return(pattern.IsMatch(left.Text) ? 0 : 1); } var obj = right as Object; if (obj != null) { Class cls = obj.Class; Value value = CompareClass(cls, left); if (value == null || value.Type == ValueType.Nil) { return(1); } Runtime.Assert(value.Type == ValueType.Object, "Case", "extract must return an Object or a nil"); return(Match(value, obj, ns, false)); } return(left.Compare(right)); } }
public override int Compare(Value value) => source.Compare(value);
public override int Compare(Value value) => innerValue.Compare(value);
public static bool Match(Value left, Value right, bool required, Block condition, string bindingName = "", bool assigning = false) { if (left is IMatch matching) { return(returnMatched(matching.Match(right), required, condition)); } if (right is BoundValue boundValue) { var fieldName = boundValue.Name; var realResult = Match(left, boundValue.InnerValue, required, condition, fieldName); if (realResult && !(boundValue.InnerValue is Class)) { Regions.SetBinding(fieldName, left, assigning); } return(realResult); } if (right is Block block) { right = block.Evaluate(); } if (left is Some leftSome) { (var someMatched, var cargoName, var cargo) = leftSome.Match(right); if (someMatched && cargoName != "_") { Regions.SetBinding(cargoName, cargo, assigning); } return(returnMatched(someMatched, required, condition)); } if (left.Type == ValueType.None && right.Type == ValueType.None) { return(returnMatched(true, required, condition)); } if (left is Failure leftFailure) { (var someMatched, var messageName, var message) = leftFailure.Match(right); if (someMatched && messageName != "_") { Regions.SetBinding(messageName, message, assigning); } return(returnMatched(someMatched, required, condition)); } if (left is List leftList) { if (right is List rightList) { return(returnMatched(leftList.Match(rightList), required, condition)); } if (right.IsNil) { return(returnMatched(false, required, condition)); } } bool leftWasAnObject; bool matched; if (right.Type != ValueType.Any && right.Type != ValueType.Placeholder) { matched = matchToLeftObject(left, right, required, condition, out leftWasAnObject, bindingName, assigning); if (leftWasAnObject) { return(returnMatched(matched, required, condition)); } } if (right is Object rightObject) { var rightClass = rightObject.Class; if (rightClass.RespondsTo("match")) { left = rightClass.StaticObject.SendToSelf("match", left); if (left?.IsNil ?? true) { return(returnMatched(false, required, condition)); } matched = matchToLeftObject(left, right, required, condition, out leftWasAnObject, bindingName, assigning); if (leftWasAnObject) { return(returnMatched(matched, required, condition)); } } } if (left is Record leftRecord && right is Record rightRecord) { return(returnMatched(leftRecord.Match(rightRecord, required), required, condition)); } if (right is AutoInvoker autoInvoker) { right = autoInvoker.Resolve(); } if (left.IsNil || right.IsNil) { return(returnMatched(false, required, condition)); } if (right is Alternation alternation) { alternation.Reset(); while (true) { var value = alternation.Dequeue(); if (value.IsNil) { return(returnMatched(false, required, condition)); } var result = Match(left, value, required, condition); if (result) { return(returnMatched(true, required, condition)); } } } if (left.ID == right.ID) { return(returnMatched(true, required, condition)); } if (left.Type == ValueType.String && right.Type == ValueType.String) { return(returnMatched(string.Compare(left.Text, right.Text, StringComparison.Ordinal) == 0, required, condition)); } switch (right.Type) { case ValueType.Any: return(returnMatched(true, required, condition)); case ValueType.TypeName: return(returnMatched(right.Compare(left) == 0, required, condition)); case ValueType.Placeholder: Regions.SetBinding(right.Text, left, assigning); return(returnMatched(true, required, condition)); case ValueType.Symbol: return(returnMatched(string.Compare(right.Text, left.Text, StringComparison.Ordinal) == 0, required, condition)); } if (right.IsArray) { var rightArray = (Array)right.SourceArray; if (left is Generator generator) { return(returnMatched(generator.Match(rightArray, required, assigning), required, condition)); } if (left.IsArray) { var leftArray = (Array)left.SourceArray; return(returnMatched(leftArray.MatchArray(rightArray, required, assigning), required, condition)); } var verb = new Equals(); return(returnMatched(verb.DoComparison(left, rightArray).IsTrue, required, condition)); } if (right.Type == ValueType.Tuple && left.Type == ValueType.Tuple) { var leftTuple = (OTuple)left; var rightTuple = (OTuple)right; return(returnMatched(leftTuple.Match(rightTuple, required, assigning), required, condition)); } switch (right.Type) { case ValueType.Block: return(returnMatched(((Block)right).IsTrue, required, condition)); case ValueType.Lambda: var closure = (Lambda)right; var variableName = closure.Parameters.VariableName(0, State.DefaultParameterNames.ValueVariable); Regions.SetBinding(variableName, left, assigning); return(returnMatched(closure.Block.Evaluate().IsTrue, required, condition)); case ValueType.Message: var message = (Message)right; return(returnMatched(message.MessageName.EndsWith("?") ? SendMessage(left, message).IsTrue : MessageManager.MessagingState.RespondsTo(left, message.MessageName), required, condition)); case ValueType.MessagePath: var messageChain = (MessagePath)right; return(returnMatched(messageChain.Invoke(left).IsTrue, required, condition)); case ValueType.Null: return(returnMatched(left.Type == ValueType.Null, required, condition)); case ValueType.Set: var set = (Set)right; return(returnMatched(set.Contains(left), required, condition)); } if (right is Unto unto) { return(returnMatched(unto.CompareTo(left), required, condition)); } if (right is Regex regex) { return(returnMatched(regex.Match(left.Text).IsTrue, required, condition)); } return(returnMatched(right is Pattern pattern ? pattern.MatchAndBind(left.Text) : Runtime.Compare(left, right) == 0, required, condition)); }
public override int Compare(Value value) => invokeableAsValue.Compare(value);