finn-lang/ast_classes.fsx

91 lines
3.0 KiB
Plaintext

type Field = { Type: string; Name: string }
type Type = { Name: string; Fields: list<Field> }
let types =
[ { Name = "Sequence"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Right" } ] }
{ Name = "Binary"
Fields =
[ { Type = "Expr"; Name = "Left" }
{ Type = "Token"; Name = "Op" }
{ Type = "Expr"; Name = "Right" } ] }
{ Name = "Grouping"
Fields = [ { Type = "Expr"; Name = "Expression" } ] }
{ Name = "Literal"
Fields =
[ { Type = "System.Object"
Name = "Value" } ] }
{ Name = "Unary"
Fields = [ { Type = "Token"; Name = "Op" }; { Type = "Expr"; Name = "Right" } ] }
{ Name = "If"
Fields =
[ { Type = "Expr"; Name = "Condition" }
{ Type = "Expr"; Name = "Then" }
{ Type = "Expr"; Name = "Else" } ] }
{ Name = "Identifier"
Fields = [ { Type = "Name"; Name = "Value" } ] }
{ Name = "List"
Fields = [ { Type = "Expr[]"; Name = "Elements" } ] }
{ Name = "Variant"
Fields = [ { Type = "Name"; Name = "Tag" }; { Type = "Expr?"; Name = "Argument" } ] }
{ Name = "Record"
Fields =
[ { Type = "Field[]"
Name = "Extensions" }
{ Type = "BaseRecord?"; Name = "Base" } ] }
{ Name = "Selector"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] }
{ Name = "Indexer"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Index" } ] }
{ Name = "Call"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr?[]"; Name = "Arguments" } ] } ]
let visitorMethod baseName t = $"visit{t.Name}{baseName}"
let renderIVisitor (sw: System.IO.StreamWriter) (baseName: string) types =
sw.Write($"public interface IVisitor<T> {{\n")
for t in types do
sw.Write($"\tT {visitorMethod baseName t}({t.Name} {baseName.ToLower()});\n")
sw.Write("}\n")
let renderType (sw: System.IO.StreamWriter) baseName t =
sw.Write
$"public class {t.Name} : {baseName}
{{\n"
for f in t.Fields do
sw.Write $"\tpublic required {f.Type} {f.Name} {{ get; init; }}\n"
sw.Write
$"\tpublic override T accept<T>(IVisitor<T> visitor)
\t{{
\t\treturn visitor.{visitorMethod baseName t}(this);
\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. //
////////////////////////////////////////////////////////////
using System;
namespace Finn.AST;
public abstract class {baseName} {{
\tpublic abstract T accept<T>(IVisitor<T> visitor);
}}\n"
renderIVisitor sw baseName types
List.iter (renderType sw baseName) types
renderAST "." "Expr" types