aa
HM1.java
Go to the documentation of this file.
1 package com.cliffc.aa.HM;
2 
3 import com.cliffc.aa.type.*;
4 import com.cliffc.aa.util.SB;
5 import com.cliffc.aa.util.VBitSet;
6 
7 import java.util.Arrays;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 
23 public class HM1 {
24  public static HMType HM(Syntax prog) {
25  HashMap<String,HMType> env = new HashMap<>();
26  // Simple types
27  HMVar bool = new HMVar(TypeInt.BOOL);
28  HMVar int64 = new HMVar(TypeInt.INT64);
29  HMVar flt64 = new HMVar(TypeFlt.FLT64);
30  HMVar strp = new HMVar(TypeMemPtr.STRPTR);
31 
32  // Primitives
33  HMVar var1 = new HMVar();
34  HMVar var2 = new HMVar();
35  env.put("pair",Oper.fun(var1, Oper.fun(var2, new Oper("pair",var1,var2))));
36 
37  HMVar var3 = new HMVar();
38  env.put("if/else" ,Oper.fun(bool,Oper.fun(var3,Oper.fun(var3,var3))));
39  env.put("if/else3",Oper.fun(bool, var3, var3,var3 ));
40 
41  env.put("dec",Oper.fun(int64,int64));
42  env.put("*" ,Oper.fun(int64,Oper.fun(int64,int64)));
43  env.put("*2" ,Oper.fun(int64, int64,int64 ));
44  env.put("==0",Oper.fun(int64,bool));
45 
46  // Convert integer to a string; int->str
47  env.put("str",Oper.fun(int64,strp));
48  // Floating point Factor; sorta like {div/mod}
49  env.put("factor",Oper.fun(flt64,new Oper("pair",flt64,flt64)));
50 
51  return prog.hm(env, new HashSet<>());
52  }
53  static void reset() { HMVar.reset(); }
54 
55 
56  public static abstract class Syntax {
57  abstract HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen);
58  }
59  public static class Con extends Syntax {
60  final Type _t;
61  Con(Type t) { _t=t; }
62  @Override public String toString() { return _t.toString(); }
63  @Override HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen) {
64  return new HMVar(_t);
65  }
66  }
67  public static class Ident extends Syntax {
68  final String _name;
69  Ident(String name) { _name=name; }
70  @Override public String toString() { return _name; }
71  @Override HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen) {
72  HMType t = env.get(_name);
73  if( t==null )
74  throw new RuntimeException("Parse error, "+_name+" is undefined");
75  HMType f = t.fresh(nongen);
76  return f;
77  }
78  }
79 
80  public static class Lambda extends Syntax {
81  final String _arg0;
82  final Syntax _body;
83  Lambda(String arg0, Syntax body) { _arg0=arg0; _body=body; }
84  @Override public String toString() { return "{ "+_arg0+" -> "+_body+" }"; }
85  @Override HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen) {
86  HMVar tnew = new HMVar();
87  // Push _arg0->tnew into env & nongen, popping them off after doing body
88  env.put(_arg0,tnew);
89  nongen.add(tnew);
90  HMType trez = _body.hm(env,nongen);
91  nongen.remove(tnew);
92  env.remove(_arg0);
93  return Oper.fun(tnew,trez);
94  }
95  }
96 
97  public static class Lambda2 extends Syntax {
98  final String _arg0, _arg1;
99  final Syntax _body;
100  Lambda2(String arg0, String arg1, Syntax body) { _arg0=arg0; _arg1=arg1; _body=body; }
101  @Override public String toString() { return "{ "+_arg0+" "+_arg1+" -> "+_body+" }"; }
102  @Override HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen) {
103  HMVar tnew0 = new HMVar();
104  HMVar tnew1 = new HMVar();
105  // Push _arg0->tnew0 into env & nongen, popping them off after doing body
106  env.put(_arg0,tnew0);
107  env.put(_arg1,tnew1);
108  nongen.add(tnew0);
109  nongen.add(tnew1);
110  HMType trez = _body.hm(env,nongen);
111  nongen.remove(tnew0);
112  nongen.remove(tnew1);
113  env.remove(_arg0);
114  env.remove(_arg1);
115  return Oper.fun(tnew0,tnew1,trez);
116  }
117  }
118 
119  public static class Let extends Syntax {
120  final String _arg0;
121  final Syntax _def, _body;
122  Let(String arg0, Syntax def, Syntax body) { _arg0=arg0; _def=def; _body=body; }
123  @Override public String toString() { return "let "+_arg0+" = "+_def+" in "+_body+" }"; }
124  @Override HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen) {
125  HMVar tndef = new HMVar();
126  // Push _arg0->tnew into env & nongen, popping them off after doing body
127  env.put(_arg0,tndef);
128  nongen.add(tndef);
129  HMType tdef = _def.hm(env,nongen);
130  nongen.remove(tndef);
131  tndef.union(tdef);
132  HMType trez = _body.hm(env,nongen);
133  env.remove(_arg0);
134  return trez;
135  }
136  }
137 
138  public static class Apply extends Syntax {
139  final Syntax _fun;
140  final Syntax[] _args;
141  Apply(Syntax fun, Syntax... args) { _fun=fun; _args=args; }
142  @Override public String toString() { return "("+_fun+" "+Arrays.deepToString(_args)+")"; }
143  @Override HMType hm(HashMap<String,HMType> env, HashSet<HMVar> nongen) {
144  HMType tfun = _fun.hm(env,nongen);
145 
146  HMType[] targs = new HMType[_args.length+1];
147  for( int i=0; i<_args.length; i++ )
148  targs[i] = _args[i].hm(env,nongen);
149  HMType trez = targs[_args.length] = new HMVar();
150  HMType nfun = Oper.fun(targs);
151  nfun.union(tfun);
152  return trez;
153  }
154  }
155 
156 
157 
158  public static abstract class HMType {
159  HMType _u; // U-F; always null for Oper
160  abstract HMType union(HMType t);
161  abstract HMType find();
162  @Override public final String toString() { return _str(new SB(),new VBitSet(),true).toString(); }
163  public String str() { return _str(new SB(),new VBitSet(),false).toString(); }
164  abstract SB _str(SB sb, VBitSet vbs, boolean debug);
165  boolean is_top() { return _u==null; }
166 
167  HMType fresh(HashSet<HMVar> nongen) {
168  HashMap<HMType,HMType> vars = new HashMap<>();
169  return _fresh(nongen,vars);
170  }
171  HMType _fresh(HashSet<HMVar> nongen, HashMap<HMType,HMType> vars) {
172  HMType t2 = find();
173  if( t2 instanceof HMVar ) {
174  return t2.occurs_in(nongen) //
175  ? t2 // Keep same var
176  : vars.computeIfAbsent(t2, e -> new HMVar(((HMVar)t2)._t));
177  } else {
178  Oper op = (Oper)t2;
179  HMType[] args = new HMType[op._args.length];
180  for( int i=0; i<args.length; i++ )
181  args[i] = op._args[i]._fresh(nongen,vars);
182  return new Oper(op._name,args);
183  }
184  }
185 
186  boolean occurs_in(HashSet<HMVar>nongen) {
187  for( HMVar x : nongen ) if( occurs_in_type(x) ) return true;
188  return false;
189  }
190  boolean occurs_in(HMType[] args) {
191  for( HMType x : args ) if( occurs_in_type(x) ) return true;
192  return false;
193  }
194  boolean occurs_in_type(HMType v) {
195  assert is_top();
196  HMType y = v.find();
197  if( y==this )
198  return true;
199  if( y instanceof Oper )
200  return occurs_in(((Oper)y)._args);
201  return false;
202  }
203  }
204 
205  static class HMVar extends HMType {
206  private Type _t;
207  private final int _uid;
208  private static int CNT;
209  HMVar() { this(Type.ANY); }
210  HMVar(Type t) { _uid=CNT++; _t=t; }
211  static void reset() { CNT=1; }
212  public Type type() { assert is_top(); return _t; }
213  @Override public SB _str(SB sb, VBitSet dups, boolean debug) {
214  if( _u!=null && !debug ) return _u._str(sb,dups,debug);
215  sb.p("v").p(_uid);
216  if( dups.tset(_uid) ) return sb.p("$");
217  if( _t!=Type.ANY ) _t.str(sb.p(":"),dups,null,false);
218  if( _u!=null ) _u._str(sb.p(">>"),dups,debug);
219  return sb;
220  }
221 
222  @Override HMType find() {
223  HMType u = _u;
224  if( u==null ) return this; // Top of union tree
225  if( u._u==null ) return u; // One-step from top
226  // Classic U-F rollup
227  while( u._u!=null ) u = u._u; // Find the top
228  HMType x = this; // Collapse all to top
229  while( x._u!=u ) { HMType tmp = x._u; x._u=u; x=tmp;}
230  return u;
231  }
232  @Override HMType union(HMType that) {
233  if( _u!=null ) return find().union(that);
234  if( that instanceof HMVar ) that = that.find();
235  if( this==that ) return this; // Do nothing
236  if( occurs_in_type(that) )
237  throw new RuntimeException("recursive unification");
238 
239  if( that instanceof HMVar ) {
240  HMVar v2 = (HMVar)that;
241  v2._t = _t.meet(v2._t);
242  }
243  else assert _t==Type.ANY; // Else this var is un-MEETd with any Con
244  return _u = that; // Classic U-F union
245  }
246  }
247 
248  static class Oper extends HMType {
249  final String _name;
250  final HMType[] _args;
251  Oper(String name, HMType... args) { _name=name; _args=args; }
252  static Oper fun(HMType... args) { return new Oper("->",args); }
253  @Override public SB _str(SB sb, VBitSet dups, boolean debug) {
254  if( _name.equals("->") ) {
255  sb.p("{ ");
256  for( int i=0; i<_args.length-1; i++ )
257  _args[i]._str(sb,dups,debug).p(" ");
258  sb.p("-> ");
259  _args[_args.length-1]._str(sb,dups,debug);
260  return sb.p(" }");
261  }
262  sb.p(_name).p('(');
263  for( HMType t : _args )
264  t._str(sb,dups,debug).p(',');
265  return sb.unchar().p(')');
266  }
267 
268  @Override HMType find() { return this; }
269  @Override HMType union(HMType that) {
270  if( !(that instanceof Oper) ) return that.union(this);
271  Oper op2 = (Oper)that;
272  if( !_name.equals(op2._name) ||
273  _args.length != op2._args.length )
274  throw new RuntimeException("Cannot unify "+this+" and "+that);
275  for( int i=0; i<_args.length; i++ )
276  _args[i].union(op2._args[i]);
277  return this;
278  }
279  }
280 }
com.cliffc.aa.HM.HM1.Lambda2._body
final Syntax _body
Definition: HM1.java:99
com.cliffc.aa.HM.HM1.HM
static HMType HM(Syntax prog)
Definition: HM1.java:24
com.cliffc.aa.HM.HM1.Lambda.toString
String toString()
Definition: HM1.java:84
com.cliffc.aa.HM.HM1.Oper
Definition: HM1.java:248
com.cliffc.aa.HM.HM1.Oper._name
final String _name
Definition: HM1.java:249
com.cliffc.aa.HM.HM1.HMType._str
abstract SB _str(SB sb, VBitSet vbs, boolean debug)
com.cliffc.aa.HM.HM1.HMVar.HMVar
HMVar(Type t)
Definition: HM1.java:210
com.cliffc.aa.HM.HM1.Let
Definition: HM1.java:119
com.cliffc.aa.HM.HM1.Apply._fun
final Syntax _fun
Definition: HM1.java:139
com.cliffc.aa.HM.HM1.Ident
Definition: HM1.java:67
com.cliffc.aa.HM.HM1.HMType._fresh
HMType _fresh(HashSet< HMVar > nongen, HashMap< HMType, HMType > vars)
Definition: HM1.java:171
com.cliffc
com.cliffc.aa.HM.HM1.Lambda2._arg0
final String _arg0
Definition: HM1.java:98
com.cliffc.aa.type.Type.toString
final String toString()
Definition: Type.java:127
com.cliffc.aa.HM.HM1.Ident._name
final String _name
Definition: HM1.java:68
com.cliffc.aa.HM.HM1.Ident.Ident
Ident(String name)
Definition: HM1.java:69
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.HM.HM1.Syntax
Definition: HM1.java:56
com.cliffc.aa.HM.HM1.HMVar
Definition: HM1.java:205
com.cliffc.aa.type.TypeInt
Definition: TypeInt.java:9
com.cliffc.aa.HM.HM1.Apply._args
final Syntax[] _args
Definition: HM1.java:140
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.type.TypeFlt
Definition: TypeFlt.java:9
com.cliffc.aa.HM.HM1.Con.Con
Con(Type t)
Definition: HM1.java:61
com.cliffc.aa.HM.HM1.HMVar.HMVar
HMVar()
Definition: HM1.java:209
com.cliffc.aa.HM.HM1.HMType.str
String str()
Definition: HM1.java:163
com.cliffc.aa.HM.HM1.HMType.toString
final String toString()
Definition: HM1.java:162
com.cliffc.aa.HM.HM1.Oper._args
final HMType[] _args
Definition: HM1.java:250
com.cliffc.aa.type.Type.ANY
static final Type ANY
Definition: Type.java:325
com.cliffc.aa.HM.HM1.Let.hm
HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
Definition: HM1.java:124
com.cliffc.aa.HM.HM1.Con.hm
HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
Definition: HM1.java:63
com.cliffc.aa.type.Type.meet
final Type meet(Type t)
Definition: Type.java:412
com.cliffc.aa.HM.HM1.HMType.occurs_in_type
boolean occurs_in_type(HMType v)
Definition: HM1.java:194
com.cliffc.aa.type.Type.str
SB str(SB sb, VBitSet dups, TypeMem mem, boolean debug)
Definition: Type.java:131
com.cliffc.aa.HM.HM1.HMVar._str
SB _str(SB sb, VBitSet dups, boolean debug)
Definition: HM1.java:213
com.cliffc.aa.HM.HM1.HMType.is_top
boolean is_top()
Definition: HM1.java:165
com.cliffc.aa.HM.HM1.HMVar._uid
final int _uid
Definition: HM1.java:207
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
com.cliffc.aa.HM.HM1.Ident.toString
String toString()
Definition: HM1.java:70
com.cliffc.aa.HM.HM1.Lambda.hm
HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
Definition: HM1.java:85
com.cliffc.aa.util.VBitSet.tset
boolean tset(int idx)
Definition: VBitSet.java:7
com.cliffc.aa.HM.HM1.Lambda2
Definition: HM1.java:97
com.cliffc.aa.HM.HM1.Syntax.hm
abstract HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
com.cliffc.aa.type.TypeInt.INT64
static final TypeInt INT64
Definition: TypeInt.java:39
com.cliffc.aa.HM.HM1.HMVar.CNT
static int CNT
Definition: HM1.java:208
com.cliffc.aa.HM.HM1.HMVar._t
Type _t
Definition: HM1.java:206
com.cliffc.aa.HM.HM1.HMVar.find
HMType find()
Definition: HM1.java:222
com.cliffc.aa.HM.HM1.HMVar.reset
static void reset()
Definition: HM1.java:211
com.cliffc.aa.HM.HM1.Apply.hm
HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
Definition: HM1.java:143
com.cliffc.aa.HM.HM1.Let._arg0
final String _arg0
Definition: HM1.java:120
com.cliffc.aa.HM.HM1.Apply.toString
String toString()
Definition: HM1.java:142
com.cliffc.aa.HM.HM1
Hindley-Milner typing.
Definition: HM1.java:23
com.cliffc.aa.HM.HM1.Apply
Definition: HM1.java:138
com.cliffc.aa.HM.HM1.Lambda
Definition: HM1.java:80
com.cliffc.aa.HM.HM1.Let._body
final Syntax _body
Definition: HM1.java:121
com.cliffc.aa.HM.HM1.Lambda._arg0
final String _arg0
Definition: HM1.java:81
com.cliffc.aa.HM.HM1.Con._t
final Type _t
Definition: HM1.java:60
com.cliffc.aa.HM.HM1.Con
Definition: HM1.java:59
com.cliffc.aa.HM.HM1.Oper._str
SB _str(SB sb, VBitSet dups, boolean debug)
Definition: HM1.java:253
com.cliffc.aa.HM.HM1.Lambda2._arg1
final String _arg1
Definition: HM1.java:98
com.cliffc.aa.HM.HM1.Let._def
final Syntax _def
Definition: HM1.java:121
com.cliffc.aa.util.VBitSet
Definition: VBitSet.java:5
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.HM.HM1.Lambda2.hm
HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
Definition: HM1.java:102
com.cliffc.aa.HM.HM1.Lambda2.toString
String toString()
Definition: HM1.java:101
com.cliffc.aa.HM.HM1.Con.toString
String toString()
Definition: HM1.java:62
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.HM.HM1.Ident.hm
HMType hm(HashMap< String, HMType > env, HashSet< HMVar > nongen)
Definition: HM1.java:71
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.HM.HM1.reset
static void reset()
Definition: HM1.java:53
com.cliffc.aa.HM.HM1.HMType.occurs_in
boolean occurs_in(HashSet< HMVar >nongen)
Definition: HM1.java:186
com.cliffc.aa.HM.HM1.HMType
Definition: HM1.java:158
com.cliffc.aa.HM.HM1.HMType.union
abstract HMType union(HMType t)
com.cliffc.aa.HM.HM1.Oper.fun
static Oper fun(HMType... args)
Definition: HM1.java:252
com.cliffc.aa.HM.HM1.Let.toString
String toString()
Definition: HM1.java:123
com.cliffc.aa.HM.HM1.Oper.Oper
Oper(String name, HMType... args)
Definition: HM1.java:251
com.cliffc.aa.HM.HM1.HMType.fresh
HMType fresh(HashSet< HMVar > nongen)
Definition: HM1.java:167
com.cliffc.aa.HM.HM1.HMType._u
HMType _u
Definition: HM1.java:159
com.cliffc.aa.type.TypeMemPtr.STRPTR
static final TypeMemPtr STRPTR
Definition: TypeMemPtr.java:97
com.cliffc.aa.HM.HM1.HMType.occurs_in
boolean occurs_in(HMType[] args)
Definition: HM1.java:190
com.cliffc.aa.HM.HM1.HMVar.union
HMType union(HMType that)
Definition: HM1.java:232
com
com.cliffc.aa.HM.HM1.Oper.find
HMType find()
Definition: HM1.java:268
com.cliffc.aa.HM.HM1.Let.Let
Let(String arg0, Syntax def, Syntax body)
Definition: HM1.java:122
com.cliffc.aa.HM.HM1.Apply.Apply
Apply(Syntax fun, Syntax... args)
Definition: HM1.java:141
com.cliffc.aa.HM.HM1.Lambda2.Lambda2
Lambda2(String arg0, String arg1, Syntax body)
Definition: HM1.java:100
com.cliffc.aa.HM.HM1.HMVar.type
Type type()
Definition: HM1.java:212
com.cliffc.aa.type.TypeInt.BOOL
static final TypeInt BOOL
Definition: TypeInt.java:43
com.cliffc.aa.util.SB.toString
String toString()
Definition: SB.java:62
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.HM.HM1.HMType.find
abstract HMType find()
com.cliffc.aa.HM.HM1.Lambda._body
final Syntax _body
Definition: HM1.java:82
com.cliffc.aa.type.TypeFlt.FLT64
static final TypeFlt FLT64
Definition: TypeFlt.java:38
com.cliffc.aa.HM.HM1.Lambda.Lambda
Lambda(String arg0, Syntax body)
Definition: HM1.java:83