From 27dd7a0e010a1d3df6ad6653909b3c1ce7018186 Mon Sep 17 00:00:00 2001 From: Will Speak Date: Fri, 21 Jun 2024 08:01:12 +0100 Subject: [PATCH] Fixup Remaining Eval Tests Introduce the form and symbol factories, and use them to implement the remaining disabled `eval` tests. --- .../Syntax/Factories.fs | 46 ++++++- src/Serehfa/Ident.cs | 2 +- test/Feersum.Tests/EvalTests.fs | 115 ++++++------------ test/Feersum.Tests/SyntaxFactoriesTests.fs | 30 +++++ 4 files changed, 110 insertions(+), 83 deletions(-) diff --git a/src/Feersum.CompilerServices/Syntax/Factories.fs b/src/Feersum.CompilerServices/Syntax/Factories.fs index 2dc9e40..f981637 100644 --- a/src/Feersum.CompilerServices/Syntax/Factories.fs +++ b/src/Feersum.CompilerServices/Syntax/Factories.fs @@ -5,18 +5,22 @@ open Firethorn.Green open Firethorn.Red open Serehfa +let private tok kind text = + GreenToken.Create(kind |> SyntaxUtils.astToGreen, text) |> GreenElement.Token + +let private atmosphere = tok AstKind.ATMOSPHERE +let private space = atmosphere " " + let private constant kind value = new Constant( SyntaxNode.CreateRoot( GreenNode.Create( AstKind.CONSTANT |> SyntaxUtils.astToGreen, - [ GreenToken.Create(kind |> SyntaxUtils.astToGreen, Write.GetExternalRepresentation(value)) - |> GreenElement.Token ] + [ tok kind (Write.GetExternalRepresentation(value)) ] ) ) ) - /// Create a Numeric Value Constant /// /// Emits a syntax tree representing a single number @@ -46,13 +50,43 @@ let quoted (e: Expression) = SyntaxNode.CreateRoot( GreenNode.Create( AstKind.QUOTED_DATUM |> SyntaxUtils.astToGreen, - [ GreenToken.Create(AstKind.QUOTE |> SyntaxUtils.astToGreen, "'") - |> GreenElement.Token - e.RawNode.Green |> GreenElement.Node ] + [ tok AstKind.QUOTE "'"; e.RawNode.Green |> GreenElement.Node ] ) ) ) +/// Wrap a String as an Identifier Node +/// +/// Produces a single well-formed symbol node contianing a single identifier. +let symbol ident = + new Symbol( + SyntaxNode.CreateRoot( + GreenNode.Create( + AstKind.SYMBOL |> SyntaxUtils.astToGreen, + [ tok AstKind.IDENTIFIER (Write.GetExternalRepresentation(new Ident(ident))) ] + ) + ) + ) + +/// Wrap a List of Expressions as a Form +/// +/// Produces a simple well-formed form expression from a list of containing expressions. +let form (exprs: Expression list) = + let close = tok AstKind.CLOSE_PAREN ")" + let toNode (x: Expression) = x.RawNode.Green |> GreenElement.Node + + let rec mapTail (exprs: Expression list) = + match exprs with + | [] -> [ close ] + | [ single ] -> [ single |> toNode; close ] + | head :: tail -> (head |> toNode) :: (space :: (mapTail tail)) + + new Form( + SyntaxNode.CreateRoot( + GreenNode.Create(AstKind.FORM |> SyntaxUtils.astToGreen, tok AstKind.OPEN_PAREN "(" :: mapTail exprs) + ) + ) + /// Wrap Expression as Script /// /// Creates a new root `ScriptProgram` from the given `Expression` diff --git a/src/Serehfa/Ident.cs b/src/Serehfa/Ident.cs index 2148e46..ce4d276 100644 --- a/src/Serehfa/Ident.cs +++ b/src/Serehfa/Ident.cs @@ -13,7 +13,7 @@ public Ident(string id) _id = string.Intern(id); } - public bool IsSimple => _id.All(c => char.IsLetterOrDigit(c)); + public bool IsSimple => _id.All(c => char.IsLetterOrDigit(c)) && _id.Length > 0; public string Raw => _id; diff --git a/test/Feersum.Tests/EvalTests.fs b/test/Feersum.Tests/EvalTests.fs index dead8ae..95c15fe 100644 --- a/test/Feersum.Tests/EvalTests.fs +++ b/test/Feersum.Tests/EvalTests.fs @@ -50,71 +50,35 @@ let ``evaluate seqs`` () = let ``Evaluate empty program`` () = Assert.Equal("; Unspecified value", interpProg ([] |> program)) -// FIXME: Eval of legacy node types - -// [] -// let ``Evaluate lambdas returns`` () = -// Assert.Equal( -// "123", -// feeri ( -// Form -// [ Form -// [ Ident "lambda" |> node -// Form [ Ident "x" |> node ] |> node -// Ident "x" |> node ] -// |> node -// Number 123.0 |> constant ] -// |> node -// ) -// ) - -// [] -// let ``Evaluate builtins`` () = -// Assert.Equal( -// "19", -// feeri ( -// Form [ Ident "+" |> node; Number 10.0 |> constant; Number 9.0 |> constant ] -// |> node -// ) -// ) - -// Assert.Equal("901", feeri (Form [ Ident "+" |> node; Number 901.0 |> constant ] |> node)) - -// Assert.Equal( -// "90", -// feeri ( -// Form [ Ident "*" |> node; Number 10.0 |> constant; Number 9.0 |> constant ] -// |> node -// ) -// ) - -// Assert.Equal( -// "901", -// feeri ( -// Form -// [ Ident "+" |> node -// Form [ Ident "*" |> node; Number 100.0 |> constant; Number 9.0 |> constant ] -// |> node -// Number 1.0 |> constant ] -// |> node -// ) -// ) - -// Assert.Equal( -// "1", -// feeri ( -// Form [ Ident "-" |> node; Number 10.0 |> constant; Number 9.0 |> constant ] -// |> node -// ) -// ) - -// Assert.Equal( -// "2", -// feeri ( -// Form [ Ident "/" |> node; Number 16.0 |> constant; Number 8.0 |> constant ] -// |> node -// ) -// ) +[] +let ``Evaluate lambdas returns`` () = + Assert.Equal( + "123", + interpScr ( + form [ form [ symbol "lambda"; form [ symbol "x" ]; symbol "x" ]; numVal 123.0 ] + |> scriptProgram + ) + ) + +[] +let ``Evaluate builtins`` () = + Assert.Equal("19", interpScr (form [ symbol "+"; numVal 10.0; numVal 9.0 ] |> scriptProgram)) + + Assert.Equal("901", interpScr (form [ symbol "+"; numVal 901.0 ] |> scriptProgram)) + + Assert.Equal("90", interpScr (form [ symbol "*"; numVal 10.0; numVal 9.0 ] |> scriptProgram)) + + Assert.Equal( + "901", + interpScr ( + form [ symbol "+"; form [ symbol "*"; numVal 100.0; numVal 9.0 ]; numVal 1.0 ] + |> scriptProgram + ) + ) + + Assert.Equal("1", interpScr (form [ symbol "-"; numVal 10.0; numVal 9.0 ] |> scriptProgram)) + + Assert.Equal("2", interpScr (form [ symbol "/"; numVal 16.0; numVal 8.0 ] |> scriptProgram)) [] [] @@ -141,17 +105,16 @@ let ``evaluate artithemtic ops`` expr result = let expr = tryReadSingle expr Assert.Equal(result, feeri (expr)) -// FIXME: Eval of legacy node types -// [] -// [] -// [")>] -// [] -// [=")>] -// [] -// let ``comp ops return true for simple cases`` op = -// Assert.Equal("#t", feeri (Form [ Ident op |> node ] |> node)) - -// Assert.Equal("#t", feeri (Form [ Ident op |> node; Number 123.456 |> constant ] |> node)) +[] +[] +[")>] +[] +[=")>] +[] +let ``comp ops return true for simple cases`` op = + Assert.Equal("#t", interpScr (form [ symbol op ] |> scriptProgram)) + + Assert.Equal("#t", interpScr (form [ symbol op; numVal 123.456 ] |> scriptProgram)) [] [] diff --git a/test/Feersum.Tests/SyntaxFactoriesTests.fs b/test/Feersum.Tests/SyntaxFactoriesTests.fs index 10533b4..b4ff862 100644 --- a/test/Feersum.Tests/SyntaxFactoriesTests.fs +++ b/test/Feersum.Tests/SyntaxFactoriesTests.fs @@ -88,3 +88,33 @@ let ``quotation exprs`` () = | _ -> failwith "Node strucutre invalid" checkReparse node + +[] +let ``simple forms`` () = + let node = form [ numVal 123; boolVal false ] + + Assert.Equal("(123 #f)", node.Text) + + Assert.True(node.DottedTail.IsNone) + + match node with + | Form([ Constant(Some(NumVal 123.0)); Constant(Some(BoolVal false)) ]) -> () + | _ -> failwith "Node structure invalid" + + checkReparse node + +[] +[] +[] +[] +[] +let ``identifier symbol exprs`` ident expected = + let node = symbol ident + + Assert.Equal(expected, node.Text) + + match node with + | Symbol id -> Assert.Equal(ident, id) + | _ -> failwith "Node strucutre invalid" + + checkReparse node