public void Replace(INameLookup names, CatExpr fxns, List <AstMacroTerm> pattern) { CatExpr pNewFxns = PatternToFxns(names, pattern); // For debugging purposes only if (Config.gbShowRewritingRuleApplications) { string sFrom = ""; for (int i = mnFxnIndex; i < mnFxnIndex + mnFxnCount; ++i) { if (i > mnFxnIndex) { sFrom += " "; } sFrom += fxns[i].msName; } string sTo = ""; for (int i = 0; i < pNewFxns.Count; ++i) { if (i > 0) { sTo += " "; } sTo += pNewFxns[i].msName; } MainClass.WriteLine("Rewriting { " + sFrom + " } to { " + sTo + " }"); } if (mnFxnIndex < fxns.Count) { fxns.RemoveRange(mnFxnIndex, mnFxnCount); } fxns.InsertRange(mnFxnIndex, pNewFxns); }
public QuotedFunction(CatExpr children, CatFxnType pFxnType) { mSubFxns = new CatExpr(children.ToArray()); msDesc = "anonymous function"; msName = "_anonymous_"; mpFxnType = new CatQuotedType(pFxnType); }
static public QuotedFunction ApplyMacros(INameLookup names, QuotedFunction f) { CatExpr list = new CatExpr(f.GetSubFxns().ToArray()); MetaCat.ApplyMacros(names, list); return(new QuotedFunction(list)); }
public QuotedFunction(QuotedFunction first, QuotedFunction second) { mSubFxns = new CatExpr(first.GetSubFxns().ToArray()); mSubFxns.AddRange(second.GetSubFxns().ToArray()); msDesc = "anonymous composed function"; msName = ""; for (int i = 0; i < mSubFxns.Count; ++i) { if (i > 0) { msName += " "; } msName += mSubFxns[i].GetName(); } try { mpFxnType = new CatQuotedType(CatTypeReconstructor.ComposeTypes(first.GetFxnType(), second.GetFxnType())); // TODO: remove once everythign tests okay. //mpFxnType = new CatQuotedType(CatTypeReconstructor.ComposeTypes(first.GetUnquotedFxnType(), second.GetUnquotedFxnType())); } catch (Exception e) { Output.WriteLine("unable to type quotation: " + ToString()); Output.WriteLine("type error: " + e.Message); mpFxnType = null; } }
static void ExpandInline(CatExpr fxns, DefinedFunction d, int nMaxDepth) { foreach (Function f in d.GetSubFxns()) { ExpandInline(fxns, f, nMaxDepth - 1); } }
static public QuotedFunction ExpandInline(QuotedFunction f, int nMaxDepth) { CatExpr ret = new CatExpr(); ExpandInline(ret, f, nMaxDepth); return(new QuotedFunction(ret)); }
static Node MakeNode(CatExpr expr) { Node ret = new Node(); ret.expr = expr; return(ret); }
public Function LiteralToFunction(string name, AstLiteral literal) { switch (literal.GetLabel()) { case AstLabel.Int: { AstInt tmp = literal as AstInt; return(new PushInt(tmp.GetValue())); } case AstLabel.Bin: { AstBin tmp = literal as AstBin; return(new PushInt(tmp.GetValue())); } case AstLabel.Char: { AstChar tmp = literal as AstChar; return(new PushValue <char>(tmp.GetValue())); } case AstLabel.String: { AstString tmp = literal as AstString; return(new PushValue <string>(tmp.GetValue())); } case AstLabel.Float: { AstFloat tmp = literal as AstFloat; return(new PushValue <double>(tmp.GetValue())); } case AstLabel.Hex: { AstHex tmp = literal as AstHex; return(new PushInt(tmp.GetValue())); } case AstLabel.Quote: { AstQuote tmp = literal as AstQuote; CatExpr fxns = NodesToFxns(name, tmp.GetTerms()); if (Config.gbOptimizeQuotations) { MetaCat.ApplyMacros(this, fxns); } return(new PushFunction(fxns)); } case AstLabel.Lambda: { AstLambda tmp = literal as AstLambda; CatLambdaConverter.Convert(tmp); CatExpr fxns = NodesToFxns(name, tmp.GetTerms()); if (Config.gbOptimizeLambdas) { MetaCat.ApplyMacros(this, fxns); } return(new PushFunction(fxns)); } default: throw new Exception("unhandled literal " + literal.ToString()); } }
static void ExpandInline(CatExpr fxns, PushFunction q, int nMaxDepth) { CatExpr tmp = new CatExpr(); foreach (Function f in q.GetChildren()) { ExpandInline(tmp, f, nMaxDepth - 1); } fxns.Add(new PushFunction(tmp)); }
private static void ApplyMacrosInner(INameLookup names, CatExpr fxns) { // Recursively apply macros for all quotations. for (int i = 0; i < fxns.Count; ++i) { if (fxns[i] is PushFunction) { PushFunction qf = fxns[i] as PushFunction; CatExpr tmp = new CatExpr(qf.GetChildren()); ApplyMacros(names, tmp); fxns[i] = new PushFunction(tmp); } } // This could be done multiple time List <MacroMatch> matches = new List <MacroMatch>(); // The peephole is the maximum size of the range of functions that we will consider // for rewriting. This helps to reduces the overall complexity of the algorithm. //int nPeephole = 20; // This is the maximum size of the sub-expression that will be considered for matching. int nMaxSubExpr = 10; // Find matches int nLastMatchPos = -1; for (int nPos = 0; nPos < fxns.Count; ++nPos) { string s = fxns[nPos].msName; if (mMacros.ContainsKey(s)) { foreach (AstMacro m in mMacros[s]) { MacroMatch match = MacroMatch.Create(m, fxns, nLastMatchPos, nPos, nMaxSubExpr); if (match != null) { nLastMatchPos = nPos; matches.Add(match); } } } } // Replace matches for (int i = matches.Count - 1; i >= 0; --i) { MacroMatch m = matches[i]; List <AstMacroTerm> pattern = m.mMacro.mDest.mPattern; m.Replace(names, fxns, pattern); } }
private void ReplaceSelfFunctions(CatExpr fxns) { for (int i = 0; i < fxns.Count; ++i) { Function f = fxns[i]; if (f is SelfFunction) { fxns[i] = this; } if (f is PushFunction) { ReplaceSelfFunctions((f as PushFunction).GetChildren()); } } }
/// <summary> /// This function is optimized to handle tail-calls with increasing the stack size. /// </summary> /// <param name="fxns"></param> public void Execute(CatExpr fxns) { int i = 0; while (i < fxns.Count) { Function f = fxns[i]; // Check if this is a tail call // if so then we are going to avoid creating a new stack frame if (i == fxns.Count - 1 && f.GetSubFxns() != null) { Trace("tail-call of '" + f.GetName() + "' function"); fxns = f.GetSubFxns(); i = 0; } else if (i == fxns.Count - 1 && f is Primitives.If) { Trace("tail-call of 'if' function"); QuotedFunction onfalse = PopFxn(); QuotedFunction ontrue = PopFxn(); if (PopBool()) { fxns = ontrue.GetSubFxns(); } else { fxns = onfalse.GetSubFxns(); } i = 0; } else if (i == fxns.Count - 1 && f is Primitives.ApplyFxn) { Trace("tail-call of 'apply' function"); QuotedFunction q = PopFxn(); fxns = q.GetSubFxns(); i = 0; } else { Trace(f.ToString()); f.Eval(this); ++i; } } }
public static Function ValueToFunction(Object o) { if (o is Int32) { return(new PushInt((int)o)); } else if (o is Double) { return(new PushValue <double>((double)o)); } else if (o is String) { return(new PushValue <string>((string)o)); } else if (o is Boolean) { bool b = (bool)o; if (b) { return(new Primitives.True()); } else { return(new Primitives.False()); } } else if (o is CatList) { return(new PushValue <CatList>(o as CatList)); } else if (o is QuotedFunction) { QuotedFunction qf = o as QuotedFunction; CatExpr fxns = qf.GetSubFxns(); PushFunction q = new PushFunction(fxns); return(q); } else { throw new Exception("Partial evaluator does not yet handle objects of type " + o); } }
public void AddFunctions(CatExpr fxns) { mFunctions.AddRange(fxns); msDesc = ""; if (Config.gbVerboseInference && Config.gbTypeChecking) { Output.WriteLine(""); Output.WriteLine("inferring type of " + msName); Output.WriteLine("==="); } try { mpFxnType = CatTypeReconstructor.Infer(mFunctions); } catch (Exception e) { Output.WriteLine("type error in function " + msName); Output.WriteLine(e.Message); mpFxnType = null; } }
public PushFunction(CatExpr children) { mSubFxns = children.GetRange(0, children.Count); msDesc = "pushes an anonymous function onto the stack"; msName = "_function_"; if (Config.gbTypeChecking) { if (Config.gbVerboseInference) { Output.WriteLine("inferring type of quoted function " + msName); } try { // Quotations can be unclear? CatFxnType childType = CatTypeReconstructor.Infer(mSubFxns); // Honestly this should never be true. if (childType == null) { throw new Exception("unknown type error"); } mpFxnType = new CatQuotedType(childType); mpFxnType = CatVarRenamer.RenameVars(mpFxnType); } catch (Exception e) { Output.WriteLine("Could not type quotation: " + msName); Output.WriteLine("Type error: " + e.Message); mpFxnType = null; } } else { mpFxnType = null; } }
public CatExpr NodesToFxns(string name, List <CatAstNode> nodes) { CatExpr result = new CatExpr(); for (int i = 0; i < nodes.Count; ++i) { CatAstNode node = nodes[i]; if (node.GetLabel().Equals(AstLabel.Name)) { string s = node.ToString(); if (s.Equals(name)) { result.Add(new SelfFunction(name)); } else { result.Add(ThrowingLookup(s)); } } else if (node is AstLiteral) { result.Add(LiteralToFunction(name, node as AstLiteral)); } else if (node is AstDef) { MakeFunction(node as AstDef); } else if (node is AstMacro) { MetaCat.AddMacro(node as AstMacro); } else { throw new Exception("unable to convert node to function: " + node.ToString()); } } return(result); }
public Function MakeFunction(AstDef def) { bool bLambda = def.mParams.Count > 0 || def.mLocals.Count > 0; if (bLambda) { CatLambdaConverter.Convert(def); } CatExpr fxns = NodesToFxns(def.mName, def.mTerms); Function ret = new DefinedFunction(def.mName, fxns); if (def.mpMetaData != null) { ret.SetMetaData(new CatMetaDataBlock(def.mpMetaData)); } if (bLambda && Config.gbOptimizeLambdas) { MetaCat.ApplyMacros(this, fxns); } AddFunction(ret); return(ret); }
static void ExpandInline(CatExpr list, Function f, int nMaxDepth) { if (nMaxDepth == 0) { list.Add(f); } else if (f is PushFunction) { ExpandInline(list, f as PushFunction, nMaxDepth); } else if (f is QuotedFunction) { ExpandInline(list, f as QuotedFunction, nMaxDepth); } else if (f is DefinedFunction) { ExpandInline(list, f as DefinedFunction, nMaxDepth); } else { list.Add(f); } }
public override bool Equals(object obj) { if (!(obj is CatExpr)) { return(false); } CatExpr expr = obj as CatExpr; if (expr.Count != this.Count) { return(false); } for (int i = 0; i < Count; ++i) { Function f = this[i]; Function g = expr[i]; if (!f.Equals(g)) { return(false); } } return(true); }
public static void ApplyMacros(INameLookup names, CatExpr fxns) { if (Config.gbShowRewritingRuleApplications) { Output.Write("Before rewriting: "); Output.WriteLine(fxns); } // repeat until a fix-point is reached (the algorithm converges) bool bDone = false; while (!bDone) { CatExpr original = fxns.Clone(); ApplyMacrosInner(names, fxns); bDone = fxns.Equals(original); } if (Config.gbShowRewritingRuleApplications) { Output.Write("After rewriting: "); Output.WriteLine(fxns); } }
public IEnumerator <Node> GetNodes(int cutAt) { if (cutAt < 0) { yield return(null); } if (cutAt >= expr.Count) { yield return(null); } CatExpr leftSubExpr = expr.GetRangeFromTo(0, cutAt); CatExpr rightSubExpr = expr.GetRangeFromTo(cutAt + 1, expr.Count - 1); Node leftNode = MakeNode(leftSubExpr); Node rightNode = MakeNode(rightSubExpr); foreach (Node node in leftNode.GetNodeIter()) { yield return(Compose(leftNode, node)); } foreach (Node node in rightNode.GetNodeIter()) { yield return(Compose(node, rightNode)); } }
public DefinedFunction(string s, CatExpr fxns) { msName = s; AddFunctions(fxns); ReplaceSelfFunctions(fxns); }
public QuotedFunction() { mSubFxns = new CatExpr(); }
public QuotedFunction(CatExpr children) : this(children, CatTypeReconstructor.Infer(children)) { }
/// <summary> /// We attempt to execute an expression (list of functions) on an empty stack. /// When no exception is raised we know that the subexpression can be replaced with anything /// that generates the values. /// </summary> static CatExpr PartialEval(Executor exec, CatExpr fxns) { // Recursively partially evaluate all quotations for (int i = 0; i < fxns.Count; ++i) { Function f = fxns[i]; if (f is PushFunction) { PushFunction q = f as PushFunction; CatExpr tmp = PartialEval(new Executor(), q.GetSubFxns()); fxns[i] = new PushFunction(tmp); } } CatExpr ret = new CatExpr(); object[] values = null; int j = 0; while (j < fxns.Count) { try { Function f = fxns[j]; if (f is DefinedFunction) { f.Eval(exec); } else { if (f.GetFxnType() == null) { throw new Exception("no type availables"); } if (f.GetFxnType().HasSideEffects()) { throw new Exception("can't perform partial execution when an expression has side-effects"); } f.Eval(exec); } // at each step, we have to get the values stored so far // since they could keep changing and any exception // will obliterate the old values. values = exec.GetStackAsArray(); } catch { if (values != null) { // Copy all of the values from the previous good execution for (int k = values.Length - 1; k >= 0; --k) { ret.Add(ValueToFunction(values[k])); } } ret.Add(fxns[j]); exec.Clear(); values = null; } j++; } if (values != null) { for (int l = values.Length - 1; l >= 0; --l) { ret.Add(ValueToFunction(values[l])); } } return(ret); }
public static Node MakeNode(CatExpr expr) { return(CodeGraph.MakeNode(expr)); }
public bool DoesTokenMatch(AstMacroTerm tkn, CatExpr x, out bool bRecoverable) { bRecoverable = true; if (tkn is AstMacroName) { bRecoverable = false; if (x.Count != 1) { return(false); } Function f = x[0]; string sName = f.GetName(); return(sName == tkn.ToString()); } else if (tkn is AstMacroTypeVar) { if (x.GetFxnType() == null) { return(false); } if (!CatFxnType.CompareFxnTypes(x.GetFxnType(), CatFxnType.PushSomethingType)) { return(false); } mCapturedVars.Add(tkn.ToString(), x); return(true); } else if (tkn is AstMacroQuote) { AstMacroQuote macroQuote = tkn as AstMacroQuote; if (x.Count != 1) { return(false); } PushFunction quote = x[0] as PushFunction; if (quote == null) { return(false); } for (int i = 0; i < macroQuote.mTerms.Count; ++i) { // Are we are at a stack variable in the matching pattern // if so it must be the last token in the pattern // e.g. [1 2 $A] is legal [1 $A 2] is not. if (macroQuote.mTerms[i] is AstMacroStackVar) { if (i != macroQuote.mTerms.Count - 1) { throw new Exception("within a quotation, expression variables can only be used in the right-most postition"); } AstMacroStackVar v = macroQuote.mTerms[0] as AstMacroStackVar; CatExpr expr = quote.GetChildren().GetRangeFrom(i); mCapturedVars.Add(v.msName, expr); return(true); } else if (macroQuote.mTerms[i] is AstMacroName) { // Well this is just an ordinary name pattern AstMacroName name = macroQuote.mTerms[i] as AstMacroName; if (quote.GetChildren().Count <= i) { return(false); } Function f = quote.GetChildren()[i]; if (!f.GetName().Equals(name.ToString())) { return(false); } } else { return(false); } } // No stack variable was encountered in the pattern // therefore the match must have been perfect, which means there are no // more terms in the input if (quote.GetChildren().Count != macroQuote.mTerms.Count) { return(false); } return(true); } else if (tkn is AstMacroStackVar) { AstMacroStackVar v = tkn as AstMacroStackVar; if (v.mType == null) { return(false); } if (x.GetFxnType() == null) { return(false); } if (!CatFxnType.CompareFxnTypes(x.GetFxnType(), v.mType)) { return(false); } mCapturedVars.Add(v.msName, x); return(true); } else { throw new Exception("unrecognized macro term " + tkn.ToString()); } }
static public MacroMatch Create(AstMacro m, CatExpr fxns, int nPrevMatchPos, int nFxnIndex, int nSubExprSize) { if (nFxnIndex < 0) { return(null); } if (nFxnIndex >= fxns.Count) { return(null); } List <AstMacroTerm> pattern = m.mSrc.mPattern; MacroMatch match = new MacroMatch(m); int nFirst = nFxnIndex; int nLast = nFxnIndex; int nTokenIndex = pattern.Count - 1; // Start at the end of the pattern and move backwards comparing expressions while (nFirst > nPrevMatchPos) { Trace.Assert(nTokenIndex <= pattern.Count); Trace.Assert(nFirst >= 0); Trace.Assert(nLast >= nFirst); Trace.Assert(nTokenIndex < pattern.Count); // get the current sub-expression that we are evaluating CatExpr expr = fxns.GetRangeFromTo(nFirst, nLast); AstMacroTerm tkn = pattern[nTokenIndex]; bool bRecoverable = false; if (match.DoesTokenMatch(tkn, expr, out bRecoverable)) { // Check if we have matched the whole pattern if (nTokenIndex == 0) { match.mnFxnIndex = nFirst; match.mnFxnCount = (nFxnIndex - nFirst) + 1; return(match); } // Go to the previous token nTokenIndex -= 1; // Adjust the sub-expression range nFirst -= 1; nLast = nFirst; } else { // Some failed matches (such as identifier names) can not be recovered from. if (!bRecoverable) { return(null); } // Widen the sub-expression. nFirst -= 1; // Check if we have passed the limit of how big of a // sub-expression will be examined if (nLast - nFirst > nSubExprSize) { return(null); } } } // The loop was finished and no match was found. return(null); }
public CatExpr PatternToFxns(INameLookup names, List <AstMacroTerm> pattern) { CatExpr ret = new CatExpr(); foreach (AstMacroTerm t in pattern) { if (t is AstMacroTypeVar) { string s = t.ToString(); if (!mCapturedVars.ContainsKey(s)) { throw new Exception("macro variable " + s + " was not captured"); } CatExpr expr = mCapturedVars[s]; ret.AddRange(expr); } else if (t is AstMacroStackVar) { string s = (t as AstMacroStackVar).msName; if (!mCapturedVars.ContainsKey(s)) { throw new Exception("macro variable " + s + " was not captured"); } CatExpr expr = mCapturedVars[s]; ret.AddRange(expr); } else if (t is AstMacroName) { string s = t.ToString(); if (s.Length < 1) { throw new Exception("internal error: macro name is empty string"); } Function f = names.ThrowingLookup(s); if (f == null) { if (Char.IsDigit(s[0])) { f = new PushInt(int.Parse(s)); } else { throw new Exception("Could not find function " + s); } } ret.Add(f); } else if (t is AstMacroQuote) { // TODO: handle typed terms within a quotation. AstMacroQuote macroQuote = t as AstMacroQuote; List <AstMacroTerm> localPattern = macroQuote.mTerms; PushFunction q = new PushFunction(PatternToFxns(names, localPattern)); ret.Add(q); } else { throw new Exception("unrecognized macro term " + t.ToString()); } } return(ret); }
public CodeGraph(CatExpr expr) { root = MakeNode(expr); }