Browse Source

Allow to expose fields of the underlying type of an abstract with a different name.

This patch allows abstracts to expose fields of the underlying type with an alias. In addition to a regular definition like @:expose(push, unshift) it also allows a definition like @:expose(push => pushEnd, unshift => pushFront). It's also possible to mix both definition types like @:expose(push, unshift => pushFront).
frabbit 12 years ago
parent
commit
e71fe7ab34
1 changed files with 11 additions and 10 deletions
  1. 11 10
      std/haxe/macro/Build.hx

+ 11 - 10
std/haxe/macro/Build.hx

@@ -68,14 +68,14 @@ class Build {
 				c;
 			case _: Context.error("Underlying type of exposing abstract must be a class", Context.currentPos());
 		}
-		function getIdentName(e) return switch(e.expr) {
-			case EConst(CIdent(s)): s;
-			case _: Context.error("Identifier expected", e.pos);
+		function getIdentNames(e) return switch(e.expr) {
+			case EConst(CIdent(s)): { field : s, newField : s };
+			case EBinop(OpArrow, { expr : EConst(CIdent(s1))}, { expr: EConst(CIdent(s2))}): { field: s1, newField : s2 };
+			case _: Context.error("Identifier or (Identifier => Identifier) expected", e.pos);
 		}
-		function toField(cf:ClassField) {
-			var name = cf.name;
+		function toField(cf:ClassField, oldName:String, newName:String) {
 			return {
-				name: name,
+				name: newName,
 				doc: cf.doc,
 				access: [AStatic, APublic, AInline],
 				pos: cf.pos,
@@ -88,7 +88,7 @@ class Build {
 							type: arg.t.toComplexType(),
 							value: null
 						});
-						var expr = macro return this.$name($a{args.map(function(arg) return macro $i{arg.name})});
+						var expr = macro return this.$oldName($a{args.map(function(arg) return macro $i{arg.name})});
 						args.unshift({name: "this", type: null, opt:false, value: null});
 						FFun({
 							args: args,
@@ -105,7 +105,8 @@ class Build {
 			}
 		}
 		for (fieldExpr in fieldExprs) {
-			var fieldName = getIdentName(fieldExpr);
+			var fieldNames = getIdentNames(fieldExpr);
+			var fieldName = fieldNames.field;
 			var cField = c.findField(fieldName, false);
 			if (cField == null) Context.error('Underlying type has no field $fieldName', fieldExpr.pos);
 			switch(cField.kind) {
@@ -113,9 +114,9 @@ class Build {
 				case _: Context.error("Only function fields can be exposed", fieldExpr.pos);
 			}
 			cField.type = map(cField.type);
-			var field = toField(cField);
+			var field = toField(cField, fieldName, fieldNames.newField);
 			fields.push(field);
 		}
 		return fields;
 	}
-}
+}