@@ -17,6 +17,7 @@ import std.option.some;
17
17
type ty_table = hashmap [ ast. def_id , @ty] ;
18
18
type env = rec ( session . session sess,
19
19
@ty_table item_types ,
20
+ hashmap[ int, @ty] bindings,
20
21
mutable int next_var_id) ;
21
22
22
23
type arg = rec ( ast. mode mode , @ty ty) ;
@@ -245,6 +246,7 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty {
245
246
// ast_ty_to_ty.
246
247
fn ast_ty_to_ty_env ( @env e , & @ast. ty ast_ty ) -> @ty {
247
248
fn getter ( @env e , ast. def_id id ) -> @ty {
249
+ check ( e. item_types . contains_key ( id) ) ;
248
250
ret e. item_types . get ( id) ;
249
251
}
250
252
auto f = bind getter ( e, _) ;
@@ -285,6 +287,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) {
285
287
fn trans_ty_item_id_to_ty ( @hashmap[ ast. def_id, @ast. item] id_to_ty_item ,
286
288
@ty_table item_to_ty ,
287
289
ast. def_id id ) -> @ty {
290
+ check ( id_to_ty_item. contains_key ( id) ) ;
288
291
auto item = id_to_ty_item. get ( id) ;
289
292
ret trans_ty_item_to_ty ( id_to_ty_item, item_to_ty, item) ;
290
293
}
@@ -317,6 +320,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) {
317
320
case ( ast. item_ty ( ?ident, ?referent_ty, ?def_id, _) ) {
318
321
if ( item_to_ty. contains_key ( def_id) ) {
319
322
// Avoid repeating work.
323
+ check ( item_to_ty. contains_key ( def_id) ) ;
320
324
ret item_to_ty. get ( def_id) ;
321
325
}
322
326
@@ -423,7 +427,7 @@ fn type_of(@ast.expr expr) -> @ty {
423
427
424
428
// Type unification
425
429
426
- fn unify ( @ty expected , @ty actual ) -> unify_result {
430
+ fn unify ( & @env e , @ty expected , @ty actual ) -> unify_result {
427
431
// Wraps the given type in an appropriate cname.
428
432
//
429
433
// TODO: This doesn't do anything yet. We should carry the cname up from
@@ -440,7 +444,7 @@ fn unify(@ty expected, @ty actual) -> unify_result {
440
444
ret ures_err( terr_mismatch, expected, actual) ;
441
445
}
442
446
443
- fn unify_step ( @ty expected , @ty actual , & hashmap [ int , @ty] bindings )
447
+ fn unify_step ( & @env e , @ty expected , @ty actual )
444
448
-> unify_result {
445
449
// TODO: rewrite this using tuple pattern matching when available, to
446
450
// avoid all this rightward drift and spikiness.
@@ -456,8 +460,7 @@ fn unify(@ty expected, @ty actual) -> unify_result {
456
460
case ( ty_box ( ?expected_sub) ) {
457
461
alt ( actual. struct ) {
458
462
case ( ty_box ( ?actual_sub) ) {
459
- auto result = unify_step( expected_sub, actual_sub,
460
- bindings) ;
463
+ auto result = unify_step ( e, expected_sub, actual_sub) ;
461
464
alt ( result) {
462
465
case ( ures_ok ( ?result_sub) ) {
463
466
ret ures_ok ( plain_ty ( ty_box ( result_sub) ) ) ;
@@ -479,8 +482,7 @@ fn unify(@ty expected, @ty actual) -> unify_result {
479
482
case ( ty_vec ( ?expected_sub) ) {
480
483
alt ( actual. struct ) {
481
484
case ( ty_vec ( ?actual_sub) ) {
482
- auto result = unify_step( expected_sub, actual_sub,
483
- bindings) ;
485
+ auto result = unify_step ( e, expected_sub, actual_sub) ;
484
486
alt ( result) {
485
487
case ( ures_ok ( ?result_sub) ) {
486
488
ret ures_ok ( plain_ty ( ty_vec ( result_sub) ) ) ;
@@ -524,9 +526,8 @@ fn unify(@ty expected, @ty actual) -> unify_result {
524
526
ret ures_err( err, expected, actual) ;
525
527
}
526
528
527
- auto result = unify_step( expected_elem. _1,
528
- actual_elem. _1,
529
- bindings) ;
529
+ auto result = unify_step ( e, expected_elem. _1 ,
530
+ actual_elem. _1 ) ;
530
531
alt ( result) {
531
532
case ( ures_ok ( ?rty) ) {
532
533
result_elems += vec ( tup ( expected_elem. _0 ,
@@ -576,9 +577,8 @@ fn unify(@ty expected, @ty actual) -> unify_result {
576
577
result_mode = ast. val ;
577
578
}
578
579
579
- auto result = unify_step( expected_input. ty,
580
- actual_input. ty,
581
- bindings) ;
580
+ auto result = unify_step ( e, expected_input. ty ,
581
+ actual_input. ty ) ;
582
582
583
583
alt ( result) {
584
584
case ( ures_ok ( ?rty) ) {
@@ -596,8 +596,8 @@ fn unify(@ty expected, @ty actual) -> unify_result {
596
596
597
597
// Check the output.
598
598
auto result_out;
599
- auto result = unify_step( expected_output,
600
- actual_output, bindings ) ;
599
+ auto result = unify_step ( e , expected_output,
600
+ actual_output) ;
601
601
alt ( result) {
602
602
case ( ures_ok ( ?rty) ) {
603
603
result_out = rty;
@@ -618,12 +618,13 @@ fn unify(@ty expected, @ty actual) -> unify_result {
618
618
}
619
619
620
620
case ( ty_var ( ?expected_id) ) {
621
- if ( bindings. contains_key( expected_id) ) {
622
- auto binding = bindings. get( expected_id) ;
623
- ret unify_step( binding, actual, bindings) ;
621
+ if ( e. bindings . contains_key ( expected_id) ) {
622
+ check ( e. bindings . contains_key ( expected_id) ) ;
623
+ auto binding = e. bindings . get ( expected_id) ;
624
+ ret unify_step( e, binding, actual) ;
624
625
}
625
626
626
- bindings. insert( expected_id, actual) ;
627
+ e . bindings . insert ( expected_id, actual) ;
627
628
ret ures_ok( actual) ;
628
629
}
629
630
}
@@ -632,19 +633,13 @@ fn unify(@ty expected, @ty actual) -> unify_result {
632
633
fail;
633
634
}
634
635
635
- fn hash_int( & int x) -> uint { ret x as uint; }
636
- fn eq_int( & int a, & int b) -> bool { ret a == b; }
637
- auto hasher = hash_int;
638
- auto eqer = eq_int;
639
- auto bindings = map. mk_hashmap[ int, @ty] ( hasher, eqer) ;
640
-
641
- ret unify_step( expected, actual, bindings) ;
636
+ ret unify_step( e, expected, actual) ;
642
637
}
643
638
644
639
// Requires that the two types unify, and prints an error message if they
645
640
// don't. Returns the unified type.
646
641
fn demand ( & @env e , & span sp, @ty expected , @ty actual ) -> @ty {
647
- alt ( unify( expected, actual) ) {
642
+ alt ( unify ( e , expected , actual ) ) {
648
643
case ( ures_ok ( ?ty) ) {
649
644
ret ty;
650
645
}
@@ -666,30 +661,45 @@ fn demand(&@env e, &span sp, @ty expected, @ty actual) -> @ty {
666
661
// with the previously-stored type for this local.
667
662
fn demand_local ( & @env e , & span sp, & @ty_table locals , ast. def_id local_id ,
668
663
@ty t ) {
664
+ check ( locals. contains_key ( local_id) ) ;
669
665
auto prev_ty = locals. get ( local_id) ;
670
666
auto unified_ty = demand ( e, sp, prev_ty, t) ;
671
667
locals. insert ( local_id, unified_ty) ;
672
668
}
673
669
674
670
// Returns true if the two types unify and false if they don't.
675
- fn are_compatible ( @ty expected , @ty actual ) -> bool {
676
- alt ( unify ( expected, actual) ) {
671
+ fn are_compatible ( & @env e , @ty expected , @ty actual ) -> bool {
672
+ alt ( unify ( e , expected, actual) ) {
677
673
case ( ures_ok ( _) ) { ret true ; }
678
674
case ( ures_err ( _, _, _) ) { ret false ; }
679
675
}
680
676
}
681
677
682
678
// Writeback: the phase that writes inferred types back into the AST.
683
679
684
- fn writeback_local ( & @ty_table locals , & span sp, @ast. local local )
680
+ fn resolve_vars ( @env e , @ty t ) -> @ty {
681
+ alt ( t. struct ) {
682
+ case ( ty_var ( ?v) ) {
683
+ check ( e. bindings . contains_key ( v) ) ;
684
+ ret resolve_vars ( e, e. bindings . get ( v) ) ;
685
+ }
686
+ }
687
+ ret t;
688
+ }
689
+
690
+ fn writeback_local ( @env e , & @ty_table locals , & span sp, @ast. local local )
685
691
-> @ast. decl {
686
- auto local_wb = @rec ( ann=ast. ann_type ( locals. get ( local. id ) ) with * local) ;
692
+ if ( !locals. contains_key ( local. id ) ) {
693
+ e. sess . err ( "unable to determine type of local: " + local. ident ) ;
694
+ }
695
+ auto local_ty = resolve_vars ( e, locals. get ( local. id ) ) ;
696
+ auto local_wb = @rec ( ann=ast. ann_type ( local_ty) with * local) ;
687
697
ret @fold. respan [ ast. decl_ ] ( sp, ast. decl_local ( local_wb) ) ;
688
698
}
689
699
690
700
fn writeback ( & @env e , & @ty_table locals , & ast . block block) -> ast . block {
691
701
auto fld = fold. new_identity_fold [ @ty_table] ( ) ;
692
- auto f = writeback_local; // FIXME: trans_const_lval bug
702
+ auto f = bind writeback_local ( e , _ , _ , _ ) ;
693
703
fld = @rec ( fold_decl_local = f with * fld) ;
694
704
ret fold. fold_block [ @ty_table] ( locals, fld, block) ;
695
705
}
@@ -753,8 +763,14 @@ fn check_expr(&@env e, &@ty_table locals, @ast.expr expr) -> @ast.expr {
753
763
case ( ast. expr_name ( ?name, ?defopt, _) ) {
754
764
auto ty = @rec ( struct=ty_nil, cname=none[ str] ) ;
755
765
alt ( option. get [ ast. def ] ( defopt) ) {
756
- case ( ast. def_arg ( ?id) ) { ty = locals. get ( id) ; }
757
- case ( ast. def_local ( ?id) ) { ty = locals. get ( id) ; }
766
+ case ( ast. def_arg ( ?id) ) {
767
+ check ( locals. contains_key ( id) ) ;
768
+ ty = locals. get ( id) ;
769
+ }
770
+ case ( ast. def_local ( ?id) ) {
771
+ check ( locals. contains_key ( id) ) ;
772
+ ty = locals. get ( id) ;
773
+ }
758
774
case ( _) {
759
775
// FIXME: handle other names.
760
776
e. sess . unimpl ( "definition variant for: "
@@ -767,6 +783,17 @@ fn check_expr(&@env e, &@ty_table locals, @ast.expr expr) -> @ast.expr {
767
783
ast. ann_type ( ty) ) ) ;
768
784
}
769
785
786
+ case ( ast. expr_assign ( ?lhs, ?rhs, _) ) {
787
+ auto lhs_1 = check_expr ( e, locals, lhs) ;
788
+ auto rhs_1 = check_expr ( e, locals, rhs) ;
789
+ auto lhs_t = type_of ( lhs_1) ;
790
+ auto rhs_t = type_of ( rhs_1) ;
791
+ demand ( e, expr. span , lhs_t, rhs_t) ;
792
+ ret @fold. respan [ ast. expr_ ] ( expr. span ,
793
+ ast. expr_assign ( lhs_1, rhs_1,
794
+ ast. ann_type ( rhs_t) ) ) ;
795
+ }
796
+
770
797
case ( _) {
771
798
// TODO
772
799
ret expr;
@@ -780,29 +807,36 @@ fn check_stmt(@env e, @ty_table locals, @ty ret_ty, &@ast.stmt stmt)
780
807
case ( ast. stmt_decl ( ?decl) ) {
781
808
alt ( decl. node ) {
782
809
case ( ast. decl_local ( ?local) ) {
783
- alt ( local. init ) {
784
- case ( none[ @ast. expr ] ) {
785
- // empty
810
+
811
+ auto local_ty;
812
+ alt ( local. ty ) {
813
+ case ( none[ @ast. ty ] ) {
814
+ // Auto slot. Assign a ty_var.
815
+ local_ty = plain_ty ( ty_var ( e. next_var_id ) ) ;
816
+ e. next_var_id += 1 ;
817
+ }
818
+
819
+ case ( some[ @ast. ty ] ( ?ast_ty) ) {
820
+ local_ty = ast_ty_to_ty_env ( e, ast_ty) ;
786
821
}
822
+ }
823
+ locals. insert ( local. id , local_ty) ;
787
824
825
+ auto rhs_ty = local_ty;
826
+ auto init = local. init ;
827
+ alt ( local. init ) {
788
828
case ( some[ @ast. expr ] ( ?expr) ) {
789
829
auto expr_t = check_expr ( e, locals, expr) ;
790
- locals. insert ( local. id , type_of ( expr_t) ) ;
791
-
792
- alt ( local. ty ) {
793
- case ( none[ @ast. ty ] ) {
794
- // Nothing to do. We'll figure out the
795
- // type later.
796
- }
797
-
798
- case ( some[ @ast. ty ] ( ?ast_ty) ) {
799
- auto ty = ast_ty_to_ty_env ( e, ast_ty) ;
800
- demand_local ( e, decl. span , locals,
801
- local. id , ty) ;
802
- }
803
- }
830
+ rhs_ty = type_of ( expr_t) ;
831
+ init = some[ @ast. expr ] ( expr_t) ;
804
832
}
805
833
}
834
+ demand ( e, decl. span , local_ty, rhs_ty) ;
835
+ auto local_1 = @rec ( init = init with * local) ;
836
+ auto decl_1 = @rec ( node=ast. decl_local ( local_1)
837
+ with * decl) ;
838
+ ret @fold. respan [ ast. stmt_ ] ( stmt. span ,
839
+ ast. stmt_decl ( decl_1) ) ;
806
840
}
807
841
808
842
case ( ast. decl_item ( _) ) {
@@ -816,7 +850,7 @@ fn check_stmt(@env e, @ty_table locals, @ty ret_ty, &@ast.stmt stmt)
816
850
case ( ast. stmt_ret ( ?expr_opt) ) {
817
851
alt ( expr_opt) {
818
852
case ( none[ @ast. expr ] ) {
819
- if ( !are_compatible ( ret_ty, plain_ty ( ty_nil) ) ) {
853
+ if ( !are_compatible ( e , ret_ty, plain_ty ( ty_nil) ) ) {
820
854
e. sess . err ( "ret; in function returning non-void" ) ;
821
855
}
822
856
@@ -846,7 +880,7 @@ fn check_stmt(@env e, @ty_table locals, @ty ret_ty, &@ast.stmt stmt)
846
880
847
881
case ( ast. stmt_expr ( ?expr) ) {
848
882
auto expr_t = check_expr ( e, locals, expr) ;
849
- if ( !are_compatible ( type_of ( expr_t) , plain_ty ( ty_nil) ) ) {
883
+ if ( !are_compatible ( e , type_of ( expr_t) , plain_ty ( ty_nil) ) ) {
850
884
// TODO: real warning function
851
885
log "warning: expression used as statement should have " +
852
886
"void type" ;
@@ -891,7 +925,16 @@ fn check_fn(&@env e, &span sp, ast.ident ident, &ast._fn f, ast.def_id id,
891
925
892
926
fn check_crate ( session . session sess, @ast. crate crate) -> @ast. crate {
893
927
auto result = collect_item_types ( crate ) ;
894
- auto e = @rec ( sess=sess, item_types=result. _1 , mutable next_var_id=0 ) ;
928
+
929
+ fn hash_int ( & int x) -> uint { ret x as uint ; }
930
+ fn eq_int ( & int a, & int b) -> bool { ret a == b; }
931
+ auto hasher = hash_int;
932
+ auto eqer = eq_int;
933
+
934
+ auto e = @rec ( sess=sess,
935
+ item_types=result. _1 ,
936
+ bindings = map. mk_hashmap [ int, @ty] ( hasher, eqer) ,
937
+ mutable next_var_id=0 ) ;
895
938
896
939
auto fld = fold. new_identity_fold [ @env] ( ) ;
897
940
auto f = check_fn; // FIXME: trans_const_lval bug
0 commit comments