TestGADT.hx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package unit;
  2. enum Constant<T> {
  3. CString(s:String):Constant<String>;
  4. CInt(s:String):Constant<Int>;
  5. CFloat(s:String):Constant<Float>;
  6. }
  7. enum Binop<S,T> {
  8. OpAdd:Binop<Float,Float>;
  9. OpEq:Binop<S,Bool>;
  10. }
  11. enum Expr<T> {
  12. EConst(c:Constant<T>):Expr<T>;
  13. EBinop<C>(op:Binop<C,T>, e1:Expr<C>, e2:Expr<C>):Expr<T>;
  14. }
  15. class TestGADT extends Test {
  16. function testBasic() {
  17. var ti = 1.22;
  18. var tb = false;
  19. var e1 = EConst(CFloat("12"));
  20. var e2 = EConst(CFloat("8"));
  21. var e3 = EConst(CFloat("12"));
  22. var eadd = EBinop(OpAdd,e1,e2);
  23. var s = eval(eadd);
  24. TestType.typedAs(s, ti);
  25. eq(s,20);
  26. var eeq = EBinop(OpEq,e1,e2);
  27. var s = eval(eeq);
  28. TestType.typedAs(s, tb);
  29. eq(s,false);
  30. var eeq = EBinop(OpEq,e1,e3);
  31. var s = eval(eeq);
  32. TestType.typedAs(s, tb);
  33. eq(s,true);
  34. }
  35. static function evalConst<T>(c:Constant<T>):T {
  36. return switch (c) {
  37. case CString(s): s;
  38. case CInt(i): Std.parseInt(i);
  39. case CFloat(f): Std.parseFloat(f);
  40. }
  41. }
  42. static function evalBinop<T,C>(op:Binop<C,T>, e1:Expr<C>, e2:Expr<C>):T {
  43. return switch(op) {
  44. case OpAdd: eval(e1) + eval(e2);
  45. case OpEq: eval(e1) == eval(e2);
  46. }
  47. }
  48. static function eval<T>(e:Expr<T>):T {
  49. return switch(e) {
  50. case EConst(c): evalConst(c);
  51. case EBinop(_op,_e1,_e2): evalBinop(_op,_e1,_e2); // TODO: this generates some unused variable warnings in macro context (issue #1675?)
  52. }
  53. }
  54. }