2023-06-25 01:15:37 +00:00
|
|
|
type Field = { Type: string; Name: string }
|
2023-09-28 00:16:19 +00:00
|
|
|
|
|
|
|
type Type =
|
|
|
|
{ Name: string
|
|
|
|
Fields: list<Field>
|
|
|
|
Start: string }
|
2023-06-25 01:15:37 +00:00
|
|
|
|
2023-08-06 21:44:15 +00:00
|
|
|
let exprTypes: Type list =
|
2023-06-28 23:18:31 +00:00
|
|
|
[ { Name = "Sequence"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Right" } ]
|
|
|
|
Start = "Left.Start" }
|
2023-06-28 23:18:31 +00:00
|
|
|
{ Name = "Binary"
|
2023-06-25 01:15:37 +00:00
|
|
|
Fields =
|
|
|
|
[ { Type = "Expr"; Name = "Left" }
|
|
|
|
{ Type = "Token"; Name = "Op" }
|
2023-08-06 21:44:15 +00:00
|
|
|
{ Type = "Expr"; Name = "Right" } ]
|
|
|
|
Start = "Left.Start" }
|
2023-06-25 01:15:37 +00:00
|
|
|
{ Name = "Grouping"
|
2023-09-28 00:16:19 +00:00
|
|
|
Fields = [ { Type = "Expr"; Name = "Expression" }; { Type = "Token"; Name = "LParen" } ]
|
|
|
|
Start = "LParen" }
|
2023-06-25 01:15:37 +00:00
|
|
|
{ Name = "Literal"
|
|
|
|
Fields =
|
|
|
|
[ { Type = "System.Object"
|
2023-09-28 00:16:19 +00:00
|
|
|
Name = "Value" }
|
|
|
|
{ Type = "Token"; Name = "Token" } ]
|
|
|
|
Start = "Token" }
|
2023-06-25 01:15:37 +00:00
|
|
|
{ Name = "Unary"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields = [ { Type = "Token"; Name = "Op" }; { Type = "Expr"; Name = "Right" } ]
|
|
|
|
Start = "Op" }
|
2023-06-28 22:26:08 +00:00
|
|
|
{ Name = "If"
|
|
|
|
Fields =
|
|
|
|
[ { Type = "Expr"; Name = "Condition" }
|
|
|
|
{ Type = "Expr"; Name = "Then" }
|
2023-08-06 21:44:15 +00:00
|
|
|
{ Type = "Expr"; Name = "Else" }
|
|
|
|
{ Type = "Token"; Name = "IfToken" } ]
|
|
|
|
Start = "IfToken" }
|
2023-07-08 03:29:17 +00:00
|
|
|
{ Name = "Variable"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields = [ { Type = "Token"; Name = "Value" } ]
|
|
|
|
Start = "Value" }
|
2023-07-02 05:13:24 +00:00
|
|
|
{ Name = "List"
|
2023-09-28 00:16:19 +00:00
|
|
|
Fields =
|
|
|
|
[ { Type = "Expr[]"; Name = "Elements" }
|
|
|
|
{ Type = "Token"; Name = "LBracket" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "LBracket" }
|
2023-07-02 05:30:24 +00:00
|
|
|
{ Name = "Variant"
|
2023-09-28 00:16:19 +00:00
|
|
|
Fields =
|
|
|
|
[ { Type = "Token"; Name = "Tag" }
|
|
|
|
{ Type = "Expr?"; Name = "Argument" }
|
|
|
|
{ Type = "Token"; Name = "Backtick" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "Backtick" }
|
2023-07-02 17:38:48 +00:00
|
|
|
{ Name = "Record"
|
|
|
|
Fields =
|
2023-07-02 17:46:18 +00:00
|
|
|
[ { Type = "Field[]"
|
|
|
|
Name = "Extensions" }
|
2023-08-06 21:44:15 +00:00
|
|
|
{ Type = "BaseRecord?"; Name = "Base" }
|
2023-09-28 00:16:19 +00:00
|
|
|
{ Type = "Token"; Name = "LBrace" } ]
|
|
|
|
Start = "LBrace" }
|
2023-07-01 06:12:02 +00:00
|
|
|
{ Name = "Selector"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Token"; Name = "FieldName" } ]
|
|
|
|
Start = "Left.Start" }
|
2023-07-02 17:46:18 +00:00
|
|
|
{ Name = "Indexer"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Index" } ]
|
|
|
|
Start = "Left.Start" }
|
2023-07-02 18:05:46 +00:00
|
|
|
{ Name = "Call"
|
2023-09-28 00:16:19 +00:00
|
|
|
Fields =
|
|
|
|
[ { Type = "Expr"; Name = "Left" }
|
|
|
|
{ Type = "Expr?[]"; Name = "Arguments" }
|
|
|
|
{ Type = "Token"; Name = "LParen" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "Left.Start" }
|
2023-07-02 22:37:06 +00:00
|
|
|
{ Name = "Let"
|
|
|
|
Fields =
|
|
|
|
[ { Type = "Binding[]"
|
|
|
|
Name = "Bindings" }
|
2023-08-06 21:44:15 +00:00
|
|
|
{ Type = "Expr"; Name = "Body" }
|
2023-09-28 00:16:19 +00:00
|
|
|
{ Type = "Token"; Name = "LetToken" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "LetToken" }
|
2023-07-05 14:52:14 +00:00
|
|
|
{ Name = "When"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields =
|
|
|
|
[ { Type = "Expr"; Name = "Head" }
|
|
|
|
{ Type = "VarBinding[]"
|
|
|
|
Name = "Cases" }
|
2023-09-28 00:16:19 +00:00
|
|
|
{ Type = "Token"; Name = "WhenToken" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "WhenToken" } ]
|
2023-06-25 01:15:37 +00:00
|
|
|
|
2023-07-02 20:56:50 +00:00
|
|
|
let patternTypes =
|
2023-07-02 22:37:06 +00:00
|
|
|
[ { Name = "SimplePattern"
|
2023-09-28 00:16:19 +00:00
|
|
|
Fields = [ { Type = "Token?"; Name = "Identifier" }; { Type = "Token"; Name = "Token" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "Token" }
|
2023-07-02 20:56:50 +00:00
|
|
|
{ Name = "VariantPattern"
|
2023-09-28 00:16:19 +00:00
|
|
|
Fields =
|
|
|
|
[ { Type = "Token"; Name = "Tag" }
|
|
|
|
{ Type = "Pattern?"; Name = "Argument" }
|
|
|
|
{ Type = "Token"; Name = "Backtick" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "Backtick" }
|
2023-07-02 20:56:50 +00:00
|
|
|
{ Name = "FieldPattern"
|
2023-08-06 21:44:15 +00:00
|
|
|
Fields = [ { Type = "Token"; Name = "Name" }; { Type = "Pattern?"; Name = "Pattern" } ]
|
|
|
|
Start = "Name" }
|
2023-07-02 20:56:50 +00:00
|
|
|
{ Name = "RecordPattern"
|
|
|
|
Fields =
|
|
|
|
[ { Type = "FieldPattern[]"
|
|
|
|
Name = "Fields" }
|
2023-07-02 22:37:06 +00:00
|
|
|
{ Type = "SimplePattern?"
|
2023-08-06 21:44:15 +00:00
|
|
|
Name = "Rest" }
|
2023-09-28 00:16:19 +00:00
|
|
|
{ Type = "Token"; Name = "LBrace" } ]
|
2023-08-06 21:44:15 +00:00
|
|
|
Start = "LBrace" } ]
|
2023-07-02 20:56:50 +00:00
|
|
|
|
2023-06-25 01:15:37 +00:00
|
|
|
let visitorMethod baseName t = $"visit{t.Name}{baseName}"
|
|
|
|
|
|
|
|
let renderIVisitor (sw: System.IO.StreamWriter) (baseName: string) types =
|
2023-07-11 06:51:51 +00:00
|
|
|
sw.Write($"public interface I{baseName}Visitor<TContext, TResult> {{\n")
|
2023-06-25 01:15:37 +00:00
|
|
|
|
|
|
|
for t in types do
|
2023-07-11 06:51:51 +00:00
|
|
|
sw.Write($"\tTResult {visitorMethod baseName t}(TContext context, {t.Name} {baseName.ToLower()});\n")
|
2023-06-25 01:15:37 +00:00
|
|
|
|
|
|
|
sw.Write("}\n")
|
|
|
|
|
|
|
|
let renderType (sw: System.IO.StreamWriter) baseName t =
|
2023-07-02 20:27:12 +00:00
|
|
|
let writeField i field =
|
2023-07-02 20:56:50 +00:00
|
|
|
if i > 0 then
|
|
|
|
sw.Write(", ")
|
|
|
|
|
|
|
|
sw.Write $"{field.Type} {field.Name}"
|
|
|
|
|
2023-07-02 20:27:12 +00:00
|
|
|
sw.Write $"public partial record {t.Name}("
|
|
|
|
List.iteri writeField t.Fields
|
2023-07-02 20:56:50 +00:00
|
|
|
|
|
|
|
sw.Write
|
2023-08-06 21:44:15 +00:00
|
|
|
$") : {baseName}({t.Start})
|
2023-06-25 01:15:37 +00:00
|
|
|
{{\n"
|
2023-07-02 20:56:50 +00:00
|
|
|
|
2023-06-25 01:15:37 +00:00
|
|
|
sw.Write
|
2023-07-11 06:51:51 +00:00
|
|
|
$"\tpublic override TResult accept<TContext, TResult>(TContext context, I{baseName}Visitor<TContext, TResult> visitor)
|
2023-06-25 01:15:37 +00:00
|
|
|
\t{{
|
2023-07-11 06:51:51 +00:00
|
|
|
\t\treturn visitor.{visitorMethod baseName t}(context, this);
|
2023-06-25 01:15:37 +00:00
|
|
|
\t}}\n"
|
|
|
|
|
|
|
|
sw.Write("}\n")
|
|
|
|
|
|
|
|
let renderAST outputDir baseName types =
|
|
|
|
let path = System.IO.Path.Combine(outputDir, baseName + ".g.cs")
|
|
|
|
use sw = new System.IO.StreamWriter(path)
|
|
|
|
|
|
|
|
sw.Write
|
|
|
|
$"////////////////////////////////////////////////////////////
|
|
|
|
// THIS FILE IS GENERATED. //
|
|
|
|
// DO NOT EDIT. //
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
2023-07-02 19:19:42 +00:00
|
|
|
#nullable enable
|
2023-07-02 05:13:24 +00:00
|
|
|
|
2023-06-25 01:15:37 +00:00
|
|
|
namespace Finn.AST;
|
|
|
|
|
2023-08-06 21:44:15 +00:00
|
|
|
public abstract record {baseName}(Token Start) {{
|
2023-07-11 06:51:51 +00:00
|
|
|
\tpublic abstract TResult accept<TContext, TResult>(TContext context, I{baseName}Visitor<TContext, TResult> visitor);
|
2023-06-25 01:15:37 +00:00
|
|
|
}}\n"
|
|
|
|
|
|
|
|
renderIVisitor sw baseName types
|
|
|
|
List.iter (renderType sw baseName) types
|
|
|
|
|
2023-07-02 20:56:50 +00:00
|
|
|
renderAST "." "Expr" exprTypes
|
|
|
|
renderAST "." "Pattern" patternTypes
|