From 70665ac786d6d17a3f2d27b42e885eb3bc9da19f Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 6 Nov 2024 13:02:16 -0600 Subject: [PATCH 1/8] Create "Add enum values as fields" --- .../Macros/add-enum-values-as-fields.md | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 assets/content/cookbook/Macros/add-enum-values-as-fields.md diff --git a/assets/content/cookbook/Macros/add-enum-values-as-fields.md b/assets/content/cookbook/Macros/add-enum-values-as-fields.md new file mode 100644 index 00000000..46fbb580 --- /dev/null +++ b/assets/content/cookbook/Macros/add-enum-values-as-fields.md @@ -0,0 +1,119 @@ +[tags]: / "expression-macro,building-fields" + +# Add enum values as fields + +This macro function adds fields corresponding to an extended type's enum type param. + +```haxe +import haxe.macro.Expr; +import haxe.macro.Context; +import haxe.macro.Type; + +using haxe.macro.Tools; + +class Macro { + public static function buildSet():Array { + final fields = Context.getBuildFields(); + + try { + return switch Context.getLocalType() { + // Extract the type parameter + case TInst(getEnumType(_.get()) => enumType, _): + // Generate fields + addFields(enumType, fields); + + fields; + case found: + throw 'Expected TInst, found: $found'; + } + } catch(e) { + Context.error(e.message, Context.currentPos()); + return Context.getBuildFields(); + } + } + + static function getEnumType(local:ClassType):EnumType { + return switch local.superClass.params { + case [_.follow() => param]: + switch param { + case TEnum(type, []): + type.get(); + case TEnum(_, _): + throw "Enums with type params are not allowed"; + case found: + throw 'T must be an Enum type, found: $found'; + } + case found: + throw 'Expected , found: $found'; + } + } + + static function addFields(enumType:EnumType, fields:Array) { + final enumCT = Context.getType(enumType.module + "." + enumType.name).toComplexType(); + + for (name => field in enumType.constructs) { + // Determine the full path of the enum field + final path = enumType.module.split("."); + path.push(enumType.name); + path.push(field.name); + + final getterName = 'get_$name'; + final newFields = (macro class TempClass { + public var $name(get, never):Bool; + + @:noCompletion inline function $getterName() return has($p{path}); + }).fields; + fields.push(newFields[0]); + fields.push(newFields[1]); + } + } +} + +``` + +## Usage + +The macro is used via [@:autoBuild](https://haxe.org/manual/macro-auto-build.html) + +```haxe +class Test { + static function main() { + final grades = new GradeSet(); + grades.add(A); + grades.add(F); + grades.add(C); + trace(grades.A); // true + trace(grades.B); // false + trace(grades.C); // true + trace(grades.D); // false + trace(grades.F); // true + } +} + +class GradeSet extends EnumSet {} + +enum Grade { A; B; C; D; F; } + +@:autoBuild(Macro.buildSet()) +class EnumSet { + final list = new Array(); + + public function new() {} + + inline public function has(value:E):Bool { + return list.contains(value); + } + + public function add(value:E) { + if (has(value) == false) + list.push(value); + } + + public function remove(value:E) { + list.remove(value); + } +} +``` +Notice that fields A, B, C, D, E and F were added to GradeSet + +> Author: [George Kurelic](https://github.com/geokureli) From e8acd2081661e3bd90bef42620c4daf7af92ced4 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 6 Nov 2024 13:15:54 -0600 Subject: [PATCH 2/8] Update add-enum-values-as-fields.md --- assets/content/cookbook/Macros/add-enum-values-as-fields.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/content/cookbook/Macros/add-enum-values-as-fields.md b/assets/content/cookbook/Macros/add-enum-values-as-fields.md index 46fbb580..6b041945 100644 --- a/assets/content/cookbook/Macros/add-enum-values-as-fields.md +++ b/assets/content/cookbook/Macros/add-enum-values-as-fields.md @@ -27,6 +27,7 @@ class Macro { throw 'Expected TInst, found: $found'; } } catch(e) { + // Catch thrown errors and point them to the failing class Context.error(e.message, Context.currentPos()); return Context.getBuildFields(); } @@ -57,6 +58,7 @@ class Macro { path.push(enumType.name); path.push(field.name); + // Create a getter that calls has() with the corresponding enum field final getterName = 'get_$name'; final newFields = (macro class TempClass { public var $name(get, never):Bool; From 0a9969053897ea240a75f077cb94ecd1689f4215 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 6 Nov 2024 13:42:48 -0600 Subject: [PATCH 3/8] More practical example --- .../Macros/add-enum-values-as-fields.md | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/assets/content/cookbook/Macros/add-enum-values-as-fields.md b/assets/content/cookbook/Macros/add-enum-values-as-fields.md index 6b041945..faa766fe 100644 --- a/assets/content/cookbook/Macros/add-enum-values-as-fields.md +++ b/assets/content/cookbook/Macros/add-enum-values-as-fields.md @@ -79,43 +79,66 @@ The macro is used via [@:autoBuild](https://haxe.org/manual/macro-auto-build.htm ```haxe class Test { - static function main() { - final grades = new GradeSet(); - grades.add(A); - grades.add(F); - grades.add(C); - trace(grades.A); // true - trace(grades.B); // false - trace(grades.C); // true - trace(grades.D); // false - trace(grades.F); // true - } + static function main() { + // poised dagger damage types + final dmg = new DamageSet([Poison, Piercing, Slashing]); + trace(dmg.Acid); // false + trace(dmg.Bludgeoning); // false + trace(dmg.Cold); // false + trace(dmg.Fire); // false + trace(dmg.Force); // false + trace(dmg.Lightning); // false + trace(dmg.Necrotic); // false + trace(dmg.Piercing); // true + trace(dmg.Poison); // true + trace(dmg.Psychic); // false + trace(dmg.Radiant); // false + trace(dmg.Slashing); // true + trace(dmg.Thunder); // false + } } -class GradeSet extends EnumSet {} - -enum Grade { A; B; C; D; F; } +class DamageSet extends EnumSet {} + +enum DamageType { + Acid; + Bludgeoning; + Cold; + Fire; + Force; + Lightning; + Necrotic; + Piercing; + Poison; + Psychic; + Radiant; + Slashing; + Thunder; +} @:autoBuild(Macro.buildSet()) class EnumSet { - final list = new Array(); + final list = new Array(); - public function new() {} + public function new(list:Array) { + for (item in list) + add(item); + } - inline public function has(value:E):Bool { - return list.contains(value); - } + inline public function has(value:E):Bool { + return list.contains(value); + } - public function add(value:E) { - if (has(value) == false) - list.push(value); - } + public function add(value:E) { + if (has(value) == false) + list.push(value); + } - public function remove(value:E) { - list.remove(value); - } + public function remove(value:E) { + list.remove(value); + } } ``` -Notice that fields A, B, C, D, E and F were added to GradeSet +Notice that fields A, B, C, D, E and F were added to DamageType > Author: [George Kurelic](https://github.com/geokureli) From 672dc9cd8451667ff619a45cdc641146c8f49fca Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 6 Nov 2024 13:44:55 -0600 Subject: [PATCH 4/8] fix explanation --- assets/content/cookbook/Macros/add-enum-values-as-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/content/cookbook/Macros/add-enum-values-as-fields.md b/assets/content/cookbook/Macros/add-enum-values-as-fields.md index faa766fe..788b4e81 100644 --- a/assets/content/cookbook/Macros/add-enum-values-as-fields.md +++ b/assets/content/cookbook/Macros/add-enum-values-as-fields.md @@ -139,6 +139,6 @@ class EnumSet { } } ``` -Notice that fields A, B, C, D, E and F were added to DamageType +Notice that a field for each `DamageType` were added to `DamageSet` > Author: [George Kurelic](https://github.com/geokureli) From 798b364bde0485ca66be92a9e445868196b5b3a6 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 6 Nov 2024 13:46:58 -0600 Subject: [PATCH 5/8] tags --- assets/content/cookbook/Macros/add-enum-values-as-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/content/cookbook/Macros/add-enum-values-as-fields.md b/assets/content/cookbook/Macros/add-enum-values-as-fields.md index 788b4e81..0fcecbc8 100644 --- a/assets/content/cookbook/Macros/add-enum-values-as-fields.md +++ b/assets/content/cookbook/Macros/add-enum-values-as-fields.md @@ -1,4 +1,4 @@ -[tags]: / "expression-macro,building-fields" +[tags]: / "autobuild-macro,building-fields" # Add enum values as fields From 4ba2f923868e2ee5be60af299f2b5a08f90a2e03 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 6 Nov 2024 13:55:06 -0600 Subject: [PATCH 6/8] Update and rename add-enum-values-as-fields.md to autobuild-fields-from-enum --- ...{add-enum-values-as-fields.md => autobuild-fields-from-enum} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename assets/content/cookbook/Macros/{add-enum-values-as-fields.md => autobuild-fields-from-enum} (98%) diff --git a/assets/content/cookbook/Macros/add-enum-values-as-fields.md b/assets/content/cookbook/Macros/autobuild-fields-from-enum similarity index 98% rename from assets/content/cookbook/Macros/add-enum-values-as-fields.md rename to assets/content/cookbook/Macros/autobuild-fields-from-enum index 0fcecbc8..fcff8c03 100644 --- a/assets/content/cookbook/Macros/add-enum-values-as-fields.md +++ b/assets/content/cookbook/Macros/autobuild-fields-from-enum @@ -1,6 +1,6 @@ [tags]: / "autobuild-macro,building-fields" -# Add enum values as fields +# Autobuild fields from enum type param This macro function adds fields corresponding to an extended type's enum type param. From 460f8aa7fdad9ea28e17a7acfa723e7980c65fd4 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 7 Nov 2024 08:30:35 -0600 Subject: [PATCH 7/8] add missing file extension --- .../{autobuild-fields-from-enum => autobuild-fields-from-enum.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename assets/content/cookbook/Macros/{autobuild-fields-from-enum => autobuild-fields-from-enum.md} (100%) diff --git a/assets/content/cookbook/Macros/autobuild-fields-from-enum b/assets/content/cookbook/Macros/autobuild-fields-from-enum.md similarity index 100% rename from assets/content/cookbook/Macros/autobuild-fields-from-enum rename to assets/content/cookbook/Macros/autobuild-fields-from-enum.md From e72cec5a5113f2975337e1047c325e6f8033603e Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 7 Nov 2024 08:35:20 -0600 Subject: [PATCH 8/8] remove unused line --- assets/content/cookbook/Macros/autobuild-fields-from-enum.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assets/content/cookbook/Macros/autobuild-fields-from-enum.md b/assets/content/cookbook/Macros/autobuild-fields-from-enum.md index fcff8c03..4330dd0c 100644 --- a/assets/content/cookbook/Macros/autobuild-fields-from-enum.md +++ b/assets/content/cookbook/Macros/autobuild-fields-from-enum.md @@ -50,8 +50,7 @@ class Macro { } static function addFields(enumType:EnumType, fields:Array) { - final enumCT = Context.getType(enumType.module + "." + enumType.name).toComplexType(); - + // Add a getter for each enum value for (name => field in enumType.constructs) { // Determine the full path of the enum field final path = enumType.module.split(".");