Guest User

Untitled

a guest
Oct 21st, 2017
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.77 KB | None | 0 0
  1. function unify(t1: Type, t2: Type): Substitution {
  2. if (t1.nodeType === "Named"
  3. && t2.nodeType === "Named"
  4. && t2.name === t1.name) {
  5. return {};
  6. } else if (t1.nodeType === "Var") {
  7. return varBind(t1.name, t2);
  8. } else if (t2.nodeType === "Var") {
  9. return varBind(t2.name, t1);
  10. } else if (t1.nodeType === "Function" && t2.nodeType === "Function") {
  11. const s1 = unify(t1.from, t2.from);
  12. const s2 = unify(
  13. applySubstToType(s1, t1.to),
  14. applySubstToType(s1, t2.to)
  15. );
  16. return composeSubst(s1, s2);
  17. } else {
  18. throw `Type mismatch:\n Expected ${typeToString(t1)}\n Found ${typeToString(t2)}`;
  19. }
  20. }
  21.  
  22. function composeSubst(s1: Substitution, s2: Substitution): Substitution {
  23. const result: Substitution = {};
  24. for (const k in s2) {
  25. const type = s2[k];
  26. result[k] = applySubstToType(s1, type);
  27. };
  28. return { ...s1, ...result };
  29. }
  30.  
  31. function varBind(name: string, t: Type): Substitution {
  32. if (t.nodeType === "Var" && t.name === name) {
  33. return {};
  34. } else if (contains(t, name)) {
  35. throw `Type ${typeToString(t)} contains a reference to itself`;
  36. } else {
  37. const subst: Substitution = {};
  38. subst[name] = t;
  39. return subst;
  40. }
  41. }
  42.  
  43. function contains(t: Type, name: string): boolean {
  44. switch (t.nodeType) {
  45. case "Named": return false;
  46. case "Var": return t.name === name;
  47. case "Function": return contains(t.from, name) || contains(t.to, name);
  48. }
  49. }
  50.  
  51. // apply given substitution to each type in the context's environment
  52. // Doesn't change the input context, but returns a new one
  53. function applySubstToCtx(subst: Substitution, ctx: Context): Context {
  54. const newContext = {
  55. ...ctx,
  56. env: {
  57. ...ctx.env
  58. }
  59. };
  60. for (const name in newContext.env) {
  61. const t = newContext.env[name];
  62. newContext.env[name] = applySubstToType(subst, t);
  63. }
  64. return newContext;
  65. }
  66.  
  67. function infer(ctx: Context, e: Expression): [Type, Substitution] {
  68. const env = ctx.env;
  69. switch (e.nodeType) {
  70. // ...
  71. case "Call":
  72. {
  73. const [funcType, s1] = infer(ctx, e.func);
  74. const [argType, s2] = infer(applySubstToCtx(s1, ctx), e.arg);
  75. const newVar = newTVar(ctx);
  76. const s3 = composeSubst(s1, s2);
  77. const s4 = unify({
  78. nodeType: "Function",
  79. from: argType,
  80. to: newVar
  81. }, funcType);
  82. const s5 = composeSubst(s3, s4);
  83. const s6 = unify(applySubstToType(s5, (funcType as TFun).from), argType);
  84. const resultSubst = composeSubst(s5, s6);
  85. return [applySubstToType(resultSubst, (funcType as TFun).to), resultSubst];
  86. }
  87. }
  88. }
Add Comment
Please, Sign In to add comment