Last active
October 16, 2021 04:38
-
-
Save nadako/7edbc859e5206b2dbd65df2fd96aa334 to your computer and use it in GitHub Desktop.
Revisions
-
nadako revised this gist
Apr 18, 2019 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -36,6 +36,16 @@ class WithMacro { case macro $i{fieldName} = $value: objectDecl.push({field: fieldName, expr: value}); overriden[fieldName] = true; case {expr: EDisplay(macro null, DKMarked), pos: p}: // toplevel completion var remainingFieldsCT = TAnonymous([ for (field in fields) if (!overriden.exists(field.name)) { pos: field.pos, name: field.name, doc: field.doc, kind: FVar(field.type.toComplexType()) } ]); return {pos: p, expr: EDisplay({pos: p, expr: EField(macro (null : $remainingFieldsCT), "")}, DKDot)}; case _: throw new Error("Invalid override expression, should be field=value", expr.pos); } -
nadako revised this gist
Mar 13, 2019 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,3 @@ #if macro import haxe.macro.Context; import haxe.macro.Expr; -
nadako revised this gist
Mar 13, 2019 . 1 changed file with 12 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ package ax3; #if macro import haxe.macro.Context; import haxe.macro.Expr; @@ -6,6 +8,16 @@ using haxe.macro.Tools; @:dce class WithMacro { /** Return a copy of a structure, replacing given fields. This provides an OCaml-like `with` syntax: ```haxe object.with(a = 13, b = "hi") // is the same as {a: 13, b: "hi", otherField: object.otherField} ``` **/ public static macro function with<T:{}>(object:ExprOf<T>, overrides:Array<Expr>):ExprOf<T> { // process given object expression and get its type var type = Context.typeof(object); -
nadako created this gist
Feb 28, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,17 @@ using WithMacro; typedef Player = { final name:String; final level:Int; } class Main { static function main() { var player = {name: "Dan", level: 15}; trace(levelUp(player)); } static function levelUp(player:Player) { return player.with(level = player.level + 1); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,55 @@ #if macro import haxe.macro.Context; import haxe.macro.Expr; using haxe.macro.Tools; #end @:dce class WithMacro { public static macro function with<T:{}>(object:ExprOf<T>, overrides:Array<Expr>):ExprOf<T> { // process given object expression and get its type var type = Context.typeof(object); // check that it's an anonymous structure and extract fields information var fields = switch type.follow() { case TAnonymous(_.get() => anon): anon.fields; case _: throw new Error("Not an anonymous structure", object.pos); } var objectDecl:Array<ObjectField> = []; var overriden = new Map(); // check field override argument expressions and add them to the new object declaration, // as well as marking them as overriden for easier checking in the second part for (expr in overrides) { switch expr { case macro $i{fieldName} = $value: objectDecl.push({field: fieldName, expr: value}); overriden[fieldName] = true; case _: throw new Error("Invalid override expression, should be field=value", expr.pos); } } // add the rest of fields from this type (those that aren't overriden) for (field in fields) { var fieldName = field.name; if (!overriden.exists(fieldName)) { // we use `tmp` as the reference for the original object, since we store it into a local var objectDecl.push({field: fieldName, expr: macro @:pos(object.pos) tmp.$fieldName}); } } // construct object declaration expression var expr = {expr: EObjectDecl(objectDecl), pos: Context.currentPos()}; // get the syntax representation of object's type var ct = type.toComplexType(); // construct the whole resulting expression. it consists of three parts: // - the `tmp` var declaration in which we store the original object // - the generated new object declaration expression (that references `tmp` for non-overriden fields) // - the type-check expression that ensures that our resulting expression is of correct type return macro @:pos(expr.pos) ({ var tmp = $object; $expr; } : $ct); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,11 @@ // Generated by Haxe 4.0.0 (git build development @ eaf32fecd) (function () { "use strict"; var Main = function() { }; Main.main = function() { console.log("Main.hx:11:",Main.levelUp({ name : "Dan", level : 15})); }; Main.levelUp = function(player) { return { level : player.level + 1, name : player.name}; }; Main.main(); })();