Skip to content

Easy macros and much more!

Compare
Choose a tag to compare
@qwertie qwertie released this 13 Jan 16:32
· 34 commits to master since this release

Allow me to showcase this release with an example. It's a slightly complicated example, but it does something cool: it converts expressions into human-readable strings. For example the expression UserIsLoggedIn && CartIsEmpty. becomes "User Is Logged In and Cart Is Empty". Then, I use a macro to combine an executable expression with its string description - all at compile-time. See here for documentation of the macro macro.

compileTime
{
   using System.Text.RegularExpressions;
   
   static string DescribeIdentifier(string id) => 
      new Regex("(?!^)[A-Z0-9]+").Replace(id, new MatchEvaluator(m => {
           string s = m.ToString();
           return s.Length > 1 
              ? " " + s.Substring(0, s.Length - 1) + " " + s.Substring(s.Length - 1) 
              : " " + s;
       }));
       
   static string DescribeExpr(LNode expr) {
      matchCode(expr) {
         case $left && $right:
            return $"{DescribeExpr(left)} and {DescribeExpr(right)}";
         case $left || $right:
            return $"{DescribeExpr(left)} or {DescribeExpr(right)}";
         case $left == $right:
            return $"{DescribeExpr(left)} is {DescribeExpr(right)}";
         case $(lit when lit.IsLiteral):
            return lit.Value?.ToString() ?? "null";
         case $_.$id:
            return DescribeIdentifier(id.Name.Name);
         default:
            return DescribeIdentifier(expr.Name.Name);
      }
   }
}

macro DocumentedExpr($expr) {
   var descr = LNode.Literal(DescribeExpr(expr));
   return quote(($descr, new Func<object>(() => $expr)));
}

class Information
{
   // These are variables, so you can change the facts to fit your taste
   static bool BidenWasElected = true, ElectionWasStolen = false;
   
   static (string,Func<object>)[] Parameters = new [] {
      DocumentedExpr(Environment.CurrentDirectory),
      DocumentedExpr(Environment.Is64BitProcess || Environment.Is64BitOperatingSystem),
      DocumentedExpr(BidenWasElected && ElectionWasStolen),
      DocumentedExpr(null == null),
   };
}

The generated code looks like this:

class Information
{
	// These are variables, so you can change the facts to fit your taste
	static bool BidenWasElected = true, ElectionWasStolen = false;

	static (string, Func<object>)[] Factoids = new[] {
		("Current Directory", new Func<object>(() => Environment.CurrentDirectory)), 
		("Is 64 Bit Process or Is 64 Bit Operating System", new Func<object>(() => Environment.Is64BitProcess || Environment.Is64BitOperatingSystem)), 
		("Biden Was Elected and Election Was Stolen", new Func<object>(() => BidenWasElected && ElectionWasStolen)), 
		("null is null", new Func<object>(() => null == null))
	};
}

The list of changes (including potentially breaking changes) is fairly massive, especially in the Loyc Core libraries. The semantic version has increased from 28 to 29, and the internal version number 2.9.0 will increase to 30.0 in the next major release, so that the semantic version will be the same as the internal version.

As always, the full list of changes is here:

Plus, you can see me talking about some of the recent changes on my YouTube channel.