Skip to content

Commit

Permalink
Added AST replacement and comments
Browse files Browse the repository at this point in the history
  • Loading branch information
dhoepelman committed Jan 29, 2015
1 parent e4435ba commit 55a933d
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 4 deletions.
5 changes: 3 additions & 2 deletions FSharpEngine/Script.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// It can be used to explore and test the library project.
// Note that script files will not be part of the project build.

#load "Module1.fs"
open Module1
#load "Transformation.fs"
open FSharpEngine.FSharpTransform


36 changes: 34 additions & 2 deletions FSharpEngine/Transformation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ type Formula =
/// List of function arguments (?)
| ArgumentList of list<Formula>

//member this.Contains = FSh


type mapElement =
| Ints of list<int>
Expand Down Expand Up @@ -256,3 +254,37 @@ let rec ApplyOn to' from source:Formula =
//try application in arguments
| Function (s, list) -> Function (s, list |> List.map (ApplyOn to' from))
| _ -> source)

type Formula with
member this.ApplyOn to' from = this |> ApplyOn to' from

let rec Contains (search:Formula) (subject:Formula) : bool =
if search = subject then
true
else
match subject with
| Function (_, arguments) | ArgumentList (arguments) -> Seq.exists (Contains search) arguments
| _ -> false

type Formula with
/// Check if the AST contains a certain subtree
member this.Contains search = this |> Contains search

// You'd think this would be better done by defining `map f ast`
// but how do you decide whether to go deeper into the tree at a Function or apply f to the function?
let rec ReplaceSubTree search replace subject : Formula =
// Found it, so replace
if subject = search then
replace
else
let doArgs arguments = arguments |> List.map (ReplaceSubTree search replace)
match subject with
// Look deeper into the AST
| Function (s, arguments) -> Function(s, doArgs arguments)
| ArgumentList (arguments) -> ArgumentList(doArgs arguments)
// No match, do nothing
| _ -> subject

type Formula with
/// Replace every occurence of an expression in an AST with another expression
member this.ReplaceSubTree search replace = this |> ReplaceSubTree search replace
91 changes: 91 additions & 0 deletions TransformationTests/FSharpASTReplacementTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FSharpEngine;
using Infotron.Parsing;
using Infotron.FSharpFormulaTransformation;

namespace TransformationTests
{
[TestClass]
public class FSharpASTReplacementTests
{
private readonly ExcelFormulaParser P = new ExcelFormulaParser();
private readonly FSharpTransformationRule T = new FSharpTransformationRule();

[TestMethod]
public void ReplaceConstant()
{
TestReplace("1", "1", "2", "2");
}

[TestMethod]
public void ReplaceCell()
{
TestReplace("D5", "D5", "E19", "E19");
}

[TestMethod]
public void DontReplaceDifferentCell()
{
TestReplace("D6", "D5", "E19", "D6");
}

[TestMethod]
public void ReplaceCellAbs()
{
TestReplace("$D$5", "D5", "E19", "E19");
}

[TestMethod]
public void ReplaceRange()
{
TestReplace("A1:A5", "A1:A5", "D1:D5", "D1:D5");
}

[TestMethod]
public void ReplaceFunction()
{
TestReplace("ABS(1)", "ABS(1)", "1", "1");
}

[TestMethod]
public void ReplaceConstantInFunction()
{
TestReplace("1 + 1", "1", "2", "2 + 2");
}

[TestMethod]
public void ReplaceCellInFunction()
{
TestReplace("D5 + 1", "D5", "E19", "E19 + 1");
}

[TestMethod]
public void ReplaceNested()
{
TestReplace("1 + 2 * 3", "2*3", "6", "1 + 6");
}

[TestMethod]
public void ReplaceBracketed()
{
TestReplace("1 + (2-3)", "2-3", "-1", "1 + (-1)");
}

private void TestReplace(string subject, string replace, string replacement, string expected)
{
var Fsub = T.CreateFSharpTree(P.ParseToTree(subject).Root);
var Frep = T.CreateFSharpTree(P.ParseToTree(replace).Root);
var Frepmnt = T.CreateFSharpTree(P.ParseToTree(replacement).Root);
var Fexp = T.CreateFSharpTree(P.ParseToTree(expected).Root);

var result = Fsub.ReplaceSubTree(Frep, Frepmnt);

Assert.AreEqual(Fexp, result);
}
}
}
1 change: 1 addition & 0 deletions TransformationTests/TransformationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="FSharpASTReplacementTests.cs" />
<Compile Include="FSharpTransformationTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down

0 comments on commit 55a933d

Please sign in to comment.