public TupleBreakExpression(int BreakIndex, int TupleSize, Expression Tuple, Expression InnerExpression) { this.BreakIndex = BreakIndex; this.TupleSize = TupleSize; this.SourceTuple = Tuple; this.InnerExpression = InnerExpression; }
public override bool Reduce(IVariableMap<Expression> Map, ref Expression Reduced) { // Is the source tuple an actual tuple? TupleExpression te = this.SourceTuple as TupleExpression; if (te != null) { // Now we got this :D Reduced = this.InnerExpression.Substitute(new SimpleMap<Expression>(this.BreakIndex, te.Parts)); return true; } // Wouldn't it be hilarious if the inner expression never even used the tuple's data? Expression cire = this.InnerExpression.Compress(this.BreakIndex, this.TupleSize); if (cire != null) { Reduced = cire; return true; } // Nope, guess i'll have to do it the normal way :( Expression tre = this.SourceTuple; Expression ire = this.InnerExpression; if (tre.Reduce(Map, ref tre) | ire.Reduce(this._CreateInner(Map), ref ire)) { Reduced = new TupleBreakExpression(this.BreakIndex, this.TupleSize, tre, ire); return true; } return false; }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { throw new NotImplementedException(); }
/// <summary> /// Creates an expression that always evaluates to the same value. /// </summary> public static ValueExpression Constant(Expression Type, Value Value) { return new ValueExpression(Value, Type); }
public override bool Reduce(IVariableMap<Expression> Map, ref Expression Reduced) { // Only possible way to reduce a variable is to replace it with its value. Expression possible = null; if (Map.Lookup(this.Index, ref possible)) { VariableExpression ve = possible as VariableExpression; if (ve != null) { if (ve.Index == this.Index) { return false; } } Reduced = possible; return true; } return false; }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { TypeSafeExpression = this; Type = this.Datum.Type; }
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 FunctionDefineExpression(int ArgumentIndex, Expression ArgumentType, Expression Function) { this.ArgumentIndex = ArgumentIndex; this.ArgumentType = ArgumentType; this.Function = Function; }
public override bool Reduce(IVariableMap<Expression> Map, ref Expression Reduced) { // Beta reduction (substituting an argument in a function definition) FunctionDefineExpression fde = this.Function as FunctionDefineExpression; if (fde != null) { Reduced = fde.SubstituteCall(this.Argument); return true; } // Recursive reduction Expression fre = this.Function; Expression are = this.Argument; if (fre.Reduce(Map, ref fre) | are.Reduce(Map, ref are)) { Reduced = new FunctionCallExpression(fre, are); return true; } return false; }
public AccessorExpression(Expression Object, string Property) { this.Object = Object; this.Property = Property; }
/// <summary> /// Prepares a parsed expression for use. /// </summary> public static Expression Prepare(Parser.Expression Expression, Scope Scope, ProgramInput Input) { // Function call Parser.FunctionCallExpression fce = Expression as Parser.FunctionCallExpression; if (fce != null) { Expression func = Prepare(fce.Function, Scope, Input); if (fce.Arguments.Count == 0) { return new FunctionCallExpression(func, TupleExpression.Empty); } if (fce.Arguments.Count == 1) { return new FunctionCallExpression(func, Prepare(fce.Arguments[0], Scope, Input)); } Expression[] args = new Expression[fce.Arguments.Count]; for (int t = 0; t < args.Length; t++) { args[t] = Prepare(fce.Arguments[t], Scope, Input); } return new FunctionCallExpression(func, new TupleExpression(args)); } // Procedure Parser.ProcedureExpression pe = Expression as Parser.ProcedureExpression; if (pe != null) { return ProcedureExpression.Prepare(pe, Scope, Input); } // Variable Parser.VariableExpression ve = Expression as Parser.VariableExpression; if (ve != null) { return PrepareVariable(ve.Name, Scope); } // Integer liteal Parser.IntegerLiteralExpression ile = Expression as Parser.IntegerLiteralExpression; if (ile != null) { return new ValueExpression(Input.GetIntegerLiteral(ile.Value), Input.IntegerLiteralType); } // Accessor Parser.AccessorExpression ae = Expression as Parser.AccessorExpression; if (ae != null) { return new AccessorExpression(Prepare(ae.Object, Scope, Input), ae.Property); } // Function definition Parser.FunctionDefineExpression fde = Expression as Parser.FunctionDefineExpression; if (fde != null) { Expression argtype; Expression inner; _PrepareLambda(fde.Arguments, fde.Definition, Scope, Input, out argtype, out inner); return new FunctionDefineExpression(Scope.NextFreeIndex, argtype, inner); } // Function type Parser.FunctionTypeExpression fte = Expression as Parser.FunctionTypeExpression; if (fte != null) { // Notice that this is almost exactly the same as a function definition? weird type system, eh? Expression argtype; Expression inner; _PrepareLambda(fte.ArgumentTypes, fte.ReturnType, Scope, Input, out argtype, out inner); return new FunctionDefineExpression(Scope.NextFreeIndex, argtype, inner); } throw new NotImplementedException(); }
/// <summary> /// Creates an expression for a function type, given the argument type and the return type(which has access to the argument in its current scope). /// </summary> public static FunctionDefineExpression FunctionType(int NextFreeIndex, Expression ArgumentType, Expression ReturnType) { return new FunctionDefineExpression(NextFreeIndex, ArgumentType, ReturnType); }
/// <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 Expression AddBinaryFunction(string Name, Expression TypeA, Expression TypeB, Expression ReturnType, BinaryFunction Handler) { return this.AddRootVariable(Name, Expression.FunctionType(this.NextFreeIndex, Expression.Tuple(TypeA, TypeB), ReturnType), new BinaryFunctionValue() { Function = Handler }); }
public _Input() { this.TypeType = this.AddUniversalType("type", null); this.IntType = this.AddRootVariable("int", this.TypeType, null); this.AddBinaryFunction("+", this.IntType, this.IntType, this.IntType, (x, y) => MakeIntValue(GetIntValue(x) + GetIntValue(y))); this.AddBinaryFunction("-", this.IntType, this.IntType, this.IntType, (x, y) => MakeIntValue(GetIntValue(x) - GetIntValue(y))); this.AddBinaryFunction("*", this.IntType, this.IntType, this.IntType, (x, y) => MakeIntValue(GetIntValue(x) * GetIntValue(y))); }
private static void _PrepareLambda( List<KeyValuePair<Parser.Expression, string>> Arguments, Parser.Expression Inner, Scope Scope, ProgramInput Input, out Expression ArgumentType, out Expression PreparedInner) { // 0 arg function if (Arguments.Count == 0) { ArgumentType = TupleExpression.Empty; PreparedInner = Prepare(Inner, Scope, Input); return; } // 1 arg function Dictionary<string, int> vars; int argloc = Scope.NextFreeIndex; Scope nscope = new Scope() { NextFreeIndex = argloc + 1, Variables = vars = new Dictionary<string, int>(), Parent = Scope }; if (Arguments.Count == 1) { var kvp = Arguments[0]; if (kvp.Value != null) { vars.Add(kvp.Value, argloc); } ArgumentType = Prepare(kvp.Key, Scope, Input); PreparedInner = Prepare(Inner, nscope, Input); return; } // 2+ arg function Expression[] types = new Expression[Arguments.Count]; for (int t = 0; t < types.Length; t++) { types[t] = Prepare(Arguments[t].Key, Scope, Input); } nscope.NextFreeIndex += types.Length; for (int t = 0; t < Arguments.Count; t++) { string argname = Arguments[t].Value; if (argname != null) { vars.Add(argname, t + argloc + 1); } } ArgumentType = Expression.Tuple(types); PreparedInner = Expression.BreakTuple( argloc + 1, Arguments.Count, Expression.Variable(argloc), Prepare(Inner, nscope, Input)); }
public FunctionCallExpression(Expression Function, Expression Argument) { this.Function = Function; this.Argument = Argument; }
/// <summary> /// Creates an expression that produces a tuple with one item. /// </summary> public static TupleExpression Tuple(Expression A) { return new TupleExpression(new Expression[] { A }); }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { int li = TypeStack.NextFreeIndex; Expression sfunc; Expression functype; this.Function.TypeCheck(TypeStack, Stack, out sfunc, out functype); FunctionDefineExpression fte; while ((fte = functype as FunctionDefineExpression) == null && functype.Reduce(Stack, ref functype)) ; if (fte == null) { throw new NotCallableException(this); } Expression sarg; Expression argtype; this.Argument.TypeCheck(TypeStack, Stack, out sarg, out argtype); FuzzyBool typeokay = Expression.Equivalent(ref argtype, ref fte.ArgumentType, Stack); if (typeokay != FuzzyBool.True) { throw new TypeCheckException(this); } TypeSafeExpression = new FunctionCallExpression(sfunc, sarg); Type = fte.Function.SubstituteOne(Stack.NextFreeIndex, sarg); }
/// <summary> /// Creates an expression that produces a tuple with three items. /// </summary> public static TupleExpression Tuple(Expression A, Expression B, Expression C) { return new TupleExpression(new Expression[] { A, B, C }); }
/// <summary> /// Creates an expression that represents the return value of the function when supplied with an argument. /// </summary> public Expression SubstituteCall(Expression Argument) { return this.Function.SubstituteOne(this.ArgumentIndex, Argument).Compress(this.ArgumentIndex, 1); }
/// <summary> /// Creates an expression with a varying amount of items. /// </summary> public static TupleExpression Tuple(Expression[] Items) { return new TupleExpression(Items); }
public ValueExpression(Value Value, Expression Type) { this.Datum = new Datum(Value, Type); }
/// <summary> /// Tries to gradually simplifies the expression. Can possibly access the map to dereference a variable. /// </summary> public virtual bool Reduce(IVariableMap<Expression> Map, ref Expression Reduced) { return false; }
/// <summary> /// Creates an expression that causes the parts in tuple to be used in the stack of the inner expression. /// </summary> public static TupleBreakExpression BreakTuple(int NextFreeIndex, int Size, Expression Tuple, Expression Inner) { return new TupleBreakExpression(NextFreeIndex, Size, Tuple, Inner); }
/// <summary> /// Substitutes a single variable in the expression. /// </summary> public Expression SubstituteOne(int Index, Expression Value) { return this.Substitute(new SingleVariableMap<Expression>(Index, Value)); }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { TypeSafeExpression = this; Type = null; TypeStack.Lookup(this.Index, ref Type); }
/// <summary> /// Creates a type-safe version of the expression by using conversions where necessary. An exception will /// be thrown if this is not possible. /// </summary> public abstract void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type);
/// <summary> /// Creates an expression that acts as a function. /// </summary> public static FunctionDefineExpression DefineFunction(int NextFreeIndex, Expression ArgumentType, Expression FunctionExpression) { return new FunctionDefineExpression(NextFreeIndex, ArgumentType, FunctionExpression); }
public override void TypeCheck( IVariableStack<Expression> TypeStack, IVariableStack<Expression> Stack, out Expression TypeSafeExpression, out Expression Type) { if (this.Parts != null && this.Parts.Length != 0) { Expression[] sparts = new Expression[this.Parts.Length]; Expression[] stypes = new Expression[this.Parts.Length]; for (int t = 0; t < this.Parts.Length; t++) { this.Parts[t].TypeCheck(TypeStack, Stack, out sparts[t], out stypes[t]); } TypeSafeExpression = new TupleExpression(sparts); Type = new TupleExpression(stypes); } else { TypeSafeExpression = Empty; Type = Empty; } }