From f21786d6b13a2d507e298de51f832daeb8a89a71 Mon Sep 17 00:00:00 2001
From: Suzanne Soy <env@suzanne.soy>
Date: Mon, 17 Aug 2020 03:41:48 +0000
Subject: [PATCH] Use .replit to customize the build command

---
 .gitignore        |   4 +-
 .replit           |   1 +
 Ast.cs            |  83 ---------------------
 AstGenerator.cs   |   4 +-
 LexerGenerated.cs | 181 ----------------------------------------------
 LexerGenerator.cs |   2 +-
 Makefile          |  18 +++++
 T4/Generators.cs  |   8 --
 T4/Generators.sh  |   8 --
 T4/T4.compileTime |  14 ----
 main.cs           |   3 -
 11 files changed, 25 insertions(+), 301 deletions(-)
 create mode 100644 .replit
 delete mode 100644 Ast.cs
 delete mode 100644 LexerGenerated.cs
 create mode 100644 Makefile
 delete mode 100644 T4/Generators.cs
 delete mode 100644 T4/Generators.sh
 delete mode 100644 T4/T4.compileTime

diff --git a/.gitignore b/.gitignore
index 2c98607..f9443e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
 /tests_results
-/main.exe
\ No newline at end of file
+/main.exe
+/*Generated.cs
+/*Generator.exe
diff --git a/.replit b/.replit
new file mode 100644
index 0000000..bf8522c
--- /dev/null
+++ b/.replit
@@ -0,0 +1 @@
+run='make'
diff --git a/Ast.cs b/Ast.cs
deleted file mode 100644
index 2a4d045..0000000
--- a/Ast.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using System;
-
-// This file was generated by Generator.cs
-
-namespace Ast {
-
-  /* To match against an instance of Expr, write:
-     x.Match(
-       Int: value => throw new NotImplementedYetException(),,
-       String: value => throw new NotImplementedYetException(),
-     )
-  */
-  public abstract class Expr {
-    public abstract T Match_<T>(Visitor<T> c);
-    public static Expr Int(int value) => new Int(value);
-    public static Expr String(string value) => new String(value);
-    public virtual Immutable.Option<Int> AsInt() => Immutable.Option.None<Int>();
-    public virtual Immutable.Option<String> AsString() => Immutable.Option.None<String>();
-    private string GetTag() {
-      return this.Match(
-        Int: value => "Int",
-        String: value => "String"
-      );
-    }
-  }
-
-  public partial class Visitor<T> { public Func<int, T> Int { get; set; } }
-
-  public sealed class Int : Expr {
-    public readonly int value;
-    public Int(int value) { this.value = value; }
-    public override T Match_<T>(Visitor<T> c) => c.Int(value);
-    public override Immutable.Option<Int> AsInt() => Immutable.Option.Some<Int>(this);
-    public override bool Equals(object other) {
-      var cast = other as Int;
-      if (Object.ReferenceEquals(cast, null)) {
-        return false;
-      } else {
-        return Equality.Field<Int, int>(this, cast, x => x.value, (x, y) => ((Object)x).Equals(y));
-      }
-    }
-    public override int GetHashCode() {
-        return HashCode.Combine("Int", this.value);
-    }
-
-    public override string ToString() => "Int";
-  }
-
-  public partial class Visitor<T> { public Func<string, T> String { get; set; } }
-
-  public sealed class String : Expr {
-    public readonly string value;
-    public String(string value) { this.value = value; }
-    public override T Match_<T>(Visitor<T> c) => c.String(value);
-    public override Immutable.Option<String> AsString() => Immutable.Option.Some<String>(this);
-    public override bool Equals(object other) {
-      var cast = other as String;
-      if (Object.ReferenceEquals(cast, null)) {
-        return false;
-      } else {
-        return Equality.Field<String, string>(this, cast, x => x.value, (x, y) => ((Object)x).Equals(y));
-      }
-    }
-    public override int GetHashCode() {
-        return HashCode.Combine("String", this.value);
-    }
-
-    public override string ToString() => "String";
-  }
-
-}
-public static class ExprExtensionMethods {
-  public static T Match<T>(
-      this Ast.Expr e,
-      Func<int, T> Int,
-      Func<string, T> String
-    ) {
-    return e.Match_(new Ast.Visitor<T> {
-      Int = Int,
-      String = String
-    });
-  }
-}
diff --git a/AstGenerator.cs b/AstGenerator.cs
index 364fa92..4aef334 100644
--- a/AstGenerator.cs
+++ b/AstGenerator.cs
@@ -3,8 +3,8 @@
 using System.Collections.Generic;
 
 public static class AstGenerator {
-  public static void Generate() {
-    Generator.Generate("Ast.cs", "namespace Ast {", "}", "Ast.", "Expr", new Dictionary<string, string> {
+  public static void Main() {
+    Generator.Generate("AstGenerated.cs", "namespace Ast {", "}", "Ast.", "Expr", new Dictionary<string, string> {
       { "Int", "int" },
       { "String", "string" },
     });
diff --git a/LexerGenerated.cs b/LexerGenerated.cs
deleted file mode 100644
index 431fd0a..0000000
--- a/LexerGenerated.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-using System;
-
-// This file was generated by Generator.cs
-
-public static partial class Lexer {
-
-  /* To match against an instance of S, write:
-     x.Match(
-       End: () => throw new NotImplementedYetException(),,
-       Space: () => throw new NotImplementedYetException(),,
-       Int: () => throw new NotImplementedYetException(),,
-       Decimal: () => throw new NotImplementedYetException(),,
-       String: () => throw new NotImplementedYetException(),,
-       StringOpen: () => throw new NotImplementedYetException(),,
-       StringClose: () => throw new NotImplementedYetException(),
-     )
-  */
-  public abstract class S {
-    public abstract T Match_<T>(Visitor<T> c);
-    public static S End = new End();
-    public static S Space = new Space();
-    public static S Int = new Int();
-    public static S Decimal = new Decimal();
-    public static S String = new String();
-    public static S StringOpen = new StringOpen();
-    public static S StringClose = new StringClose();
-    public virtual Immutable.Option<End> AsEnd() => Immutable.Option.None<End>();
-    public virtual Immutable.Option<Space> AsSpace() => Immutable.Option.None<Space>();
-    public virtual Immutable.Option<Int> AsInt() => Immutable.Option.None<Int>();
-    public virtual Immutable.Option<Decimal> AsDecimal() => Immutable.Option.None<Decimal>();
-    public virtual Immutable.Option<String> AsString() => Immutable.Option.None<String>();
-    public virtual Immutable.Option<StringOpen> AsStringOpen() => Immutable.Option.None<StringOpen>();
-    public virtual Immutable.Option<StringClose> AsStringClose() => Immutable.Option.None<StringClose>();
-    private string GetTag() {
-      return this.Match(
-        End: () => "End",
-        Space: () => "Space",
-        Int: () => "Int",
-        Decimal: () => "Decimal",
-        String: () => "String",
-        StringOpen: () => "StringOpen",
-        StringClose: () => "StringClose"
-      );
-    }
-  }
-
-  public partial class Visitor<T> { public Func<T> End { get; set; } }
-
-  public sealed class End : S {
-    public End() { }
-    public override T Match_<T>(Visitor<T> c) => c.End();
-    public override Immutable.Option<End> AsEnd() => Immutable.Option.Some<End>(this);
-    public override bool Equals(object other) {
-        return (other is End);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "End";
-  }
-
-  public partial class Visitor<T> { public Func<T> Space { get; set; } }
-
-  public sealed class Space : S {
-    public Space() { }
-    public override T Match_<T>(Visitor<T> c) => c.Space();
-    public override Immutable.Option<Space> AsSpace() => Immutable.Option.Some<Space>(this);
-    public override bool Equals(object other) {
-        return (other is Space);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "Space";
-  }
-
-  public partial class Visitor<T> { public Func<T> Int { get; set; } }
-
-  public sealed class Int : S {
-    public Int() { }
-    public override T Match_<T>(Visitor<T> c) => c.Int();
-    public override Immutable.Option<Int> AsInt() => Immutable.Option.Some<Int>(this);
-    public override bool Equals(object other) {
-        return (other is Int);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "Int";
-  }
-
-  public partial class Visitor<T> { public Func<T> Decimal { get; set; } }
-
-  public sealed class Decimal : S {
-    public Decimal() { }
-    public override T Match_<T>(Visitor<T> c) => c.Decimal();
-    public override Immutable.Option<Decimal> AsDecimal() => Immutable.Option.Some<Decimal>(this);
-    public override bool Equals(object other) {
-        return (other is Decimal);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "Decimal";
-  }
-
-  public partial class Visitor<T> { public Func<T> String { get; set; } }
-
-  public sealed class String : S {
-    public String() { }
-    public override T Match_<T>(Visitor<T> c) => c.String();
-    public override Immutable.Option<String> AsString() => Immutable.Option.Some<String>(this);
-    public override bool Equals(object other) {
-        return (other is String);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "String";
-  }
-
-  public partial class Visitor<T> { public Func<T> StringOpen { get; set; } }
-
-  public sealed class StringOpen : S {
-    public StringOpen() { }
-    public override T Match_<T>(Visitor<T> c) => c.StringOpen();
-    public override Immutable.Option<StringOpen> AsStringOpen() => Immutable.Option.Some<StringOpen>(this);
-    public override bool Equals(object other) {
-        return (other is StringOpen);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "StringOpen";
-  }
-
-  public partial class Visitor<T> { public Func<T> StringClose { get; set; } }
-
-  public sealed class StringClose : S {
-    public StringClose() { }
-    public override T Match_<T>(Visitor<T> c) => c.StringClose();
-    public override Immutable.Option<StringClose> AsStringClose() => Immutable.Option.Some<StringClose>(this);
-    public override bool Equals(object other) {
-        return (other is StringClose);
-    }
-    public override int GetHashCode() {
-        return "C".GetHashCode();
-    }
-
-    public override string ToString() => "StringClose";
-  }
-
-}
-public static class SExtensionMethods {
-  public static T Match<T>(
-      this Lexer.S e,
-      Func<T> End,
-      Func<T> Space,
-      Func<T> Int,
-      Func<T> Decimal,
-      Func<T> String,
-      Func<T> StringOpen,
-      Func<T> StringClose
-    ) {
-    return e.Match_(new Lexer.Visitor<T> {
-      End = End,
-      Space = Space,
-      Int = Int,
-      Decimal = Decimal,
-      String = String,
-      StringOpen = StringOpen,
-      StringClose = StringClose
-    });
-  }
-}
diff --git a/LexerGenerator.cs b/LexerGenerator.cs
index 2e06724..7fb74cd 100644
--- a/LexerGenerator.cs
+++ b/LexerGenerator.cs
@@ -3,7 +3,7 @@
 using System.Collections.Generic;
 
 public static class LexerGenerator {
-  public static void Generate() {
+  public static void Main() {
     Generator.Generate("LexerGenerated.cs", "public static partial class Lexer {", "}", "Lexer.", "S", new Dictionary<string, string> {
       { "End", null },
       { "Space", null },
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ce83160
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+CS := $(shell find . -not \( -path ./.git \) -not \( -name '*Generator.cs' \) -name '*.cs')
+GENERATORS := $(shell find . -not \( -path ./.git \) -not \( -path ./T4/Generator.cs \) -name '*Generator.cs')
+GENERATED := $(patsubst %Generator.cs,%Generated.cs,$(GENERATORS))
+
+.PHONY: run
+run: main.exe
+	mono main.exe
+
+main.exe: $(sort $(CS) $(GENERATED))
+	mcs -out:$@ $^
+
+%Generated.cs: .%Generator.exe
+	mono $<
+
+.%Generator.exe: %Generator.cs
+	mcs -out:$@ T4/Generator.cs $<
+
+
diff --git a/T4/Generators.cs b/T4/Generators.cs
deleted file mode 100644
index 890189b..0000000
--- a/T4/Generators.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-// Run with: sh ./T4/Generators.sh
-
-public static class Generators {
-  public static void Generate() {
-    AstGenerator.Generate();
-    LexerGenerator.Generate();
-  }
-}
\ No newline at end of file
diff --git a/T4/Generators.sh b/T4/Generators.sh
deleted file mode 100644
index ef67f56..0000000
--- a/T4/Generators.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-# Run with: sh ./T4/Generators.sh
-
-set -e
-set -x
-
-mcs -out:T4.exe T4/Generator.cs T4/Generators.cs LexerGenerator.cs AstGenerator.cs T4/T4.compileTime && mono T4.exe
diff --git a/T4/T4.compileTime b/T4/T4.compileTime
deleted file mode 100644
index ec75810..0000000
--- a/T4/T4.compileTime
+++ /dev/null
@@ -1,14 +0,0 @@
-// Run with: sh ./T4/Generators.sh
-
-// Workaround to start the compile-time code generation
-// repl.it lacks T4, if the generated code is out of sync it's not
-// possible to build main.exe, and there can't be a fallback Main
-// method with a .cs extension (the C# compiler complains there are
-// two implementations of Main, and repl.it's command-line lacks
-// the option to specify which class to use).
-
-public static class MainClass {
-  public static void Main() {
-    Generators.Generate();
-  }
-}
\ No newline at end of file
diff --git a/main.cs b/main.cs
index 06f07ba..6622d1e 100644
--- a/main.cs
+++ b/main.cs
@@ -57,9 +57,6 @@ public static class MainClass {
   }
 
   public static void Main (string[] args) {
-    // Refresh code generated at compile-time
-    Generators.Generate();
-
     if (args.Length != 1) {
       Console.WriteLine("Usage: mono main.exe path/to/file.e");
       Console.WriteLine("");