/// <summary> /// Gets if the two specified expressions are equivalent. This function reduces and subsitutes /// given expressions and the stack as needed to get an accurate result. /// </summary> public static FuzzyBool Equivalent(ref Expression A, ref Expression B, IVariableStack<Expression> Stack) { if (A == B) { return FuzzyBool.True; } while (true) { // Variable equality VariableExpression va = A as VariableExpression; if (va != null) { VariableExpression vb = B as VariableExpression; if (vb != null) { if (va.Index == vb.Index) { return FuzzyBool.True; } } } // Tuple equality TupleExpression at = A as TupleExpression; if (at != null) { TupleExpression bt = B as TupleExpression; if (bt != null) { if (at.Parts.Length != bt.Parts.Length) { return FuzzyBool.False; } for (int t = 0; t < at.Parts.Length; t++) { FuzzyBool pe = Equivalent(ref at.Parts[t], ref bt.Parts[t], Stack); if (pe == FuzzyBool.False) { return FuzzyBool.False; } if (pe == FuzzyBool.Undetermined) { return FuzzyBool.Undetermined; } } return FuzzyBool.True; } } // Tuple break TupleBreakExpression atb = A as TupleBreakExpression; if (atb != null) { TupleBreakExpression btb = B as TupleBreakExpression; if (btb != null) { return FuzzyBoolLogic.And( Expression.Equivalent(ref atb.SourceTuple, ref btb.SourceTuple, Stack), Expression.Equivalent(ref atb.InnerExpression, ref btb.InnerExpression, Stack)); } } // Function definition equality FunctionDefineExpression afd = A as FunctionDefineExpression; if (afd != null) { FunctionDefineExpression bfd = B as FunctionDefineExpression; if (bfd != null) { if (afd.ArgumentIndex == bfd.ArgumentIndex) { var nstack = Stack.Cut(afd.ArgumentIndex).Append(new Expression[] { Expression.Variable(afd.ArgumentIndex) }); return FuzzyBoolLogic.And( Expression.Equivalent(ref afd.ArgumentType, ref bfd.ArgumentType, nstack), Expression.Equivalent(ref afd.Function, ref bfd.Function, nstack)); } } } // Nothing yet? try reducing if (A.Reduce(Stack, ref A) | B.Reduce(Stack, ref B)) { continue; } else { break; } } return FuzzyBool.Undetermined; }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { Expression sifunc; Expression itype; this.Function.TypeCheck( TypeStack.Cut(this.ArgumentIndex).Append(new Expression[] { this.ArgumentType }), Stack.Cut(this.ArgumentIndex).Append(new Expression[] { Expression.Variable(Stack.NextFreeIndex) }), out sifunc, out itype); Type = Expression.FunctionType(this.ArgumentIndex, this.ArgumentType, itype); TypeSafeExpression = new FunctionDefineExpression(this.ArgumentIndex, this.ArgumentType, sifunc); }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { Expression stuple; Expression tupletype; this.SourceTuple.TypeCheck(TypeStack, Stack, out stuple, out tupletype); TupleExpression te; while ((te = tupletype as TupleExpression) == null && tupletype.Reduce(Stack, ref tupletype)) ; if (te == null) { throw new NotImplementedException(); } TupleExpression se; while ((se = stuple as TupleExpression) == null && stuple.Reduce(Stack, ref stuple)) ; Expression[] stackappend; if (se != null) { stackappend = se.Parts ?? new Expression[0]; if (stackappend.Length != this.TupleSize) { throw new NotImplementedException(); } } else { if (te.Parts.Length != this.TupleSize) { throw new NotImplementedException(); } stackappend = new Expression[te.Parts.Length]; int ni = Stack.NextFreeIndex; for (int t = 0; t < te.Parts.Length; t++) { stackappend[t] = Expression.Variable(t + ni); } } Expression si; Expression itype; this.InnerExpression.TypeCheck( TypeStack.Cut(this.BreakIndex).Append(te.Parts ?? new Expression[0]), Stack.Cut(this.BreakIndex).Append(stackappend), out si, out itype); TypeSafeExpression = new TupleBreakExpression(this.BreakIndex, this.TupleSize, stuple, si); Type = itype; }