-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathesop-formal-model.tex
1699 lines (1558 loc) · 59.7 KB
/
esop-formal-model.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{A Formal Model of \lambdatc{}}
\label{sec:formal}
After demonstrating the core features of Typed Clojure,
we link them together in a formal model called
\lambdatc{}.
%
Building on occurrence typing,
we incrementally add each
novel feature of Typed Clojure to the formalism,
interleaving presentation of syntax, typing rules, operational semantics,
and subtyping.
\section{Core type system}
\label{sec:coretypesystem}
We start with a review of
occurrence typing~\cite{TF10}, the foundation of \lambdatc{}.
%We build up the occurrence typing calculus for illustrative purposes,
%and present the full syntax at the end of the section.
\paragraph{Expressions} Syntax is given in \figref{main:figure:termsyntax}. Expressions \e{}
include variables \x{}, values \v{},
applications, abstractions, conditionals, and let expressions.
All binding forms introduce fresh variables---a subtle but important point since our type environments
are not simply dictionaries.
Values include booleans \bool{}, \nil{}, class literals {\class{}}, keywords \k{},
integers {\nat{}},
constants {\const{}}, and strings \str{}. Lexical closures {\closure {\openv{}} {\abs {\x{}} {\t{}} {\e{}}}}
close value environments \openv{}---which map bindings to values---over functions.
\paragraph{Types} Types \s{} or \t{}
include the top type \Top,
\emph{untagged} unions {\Unionsplice {\overrightarrow{\t{}}}},
singletons ${\Value \singletonmeta{}}$,
and class instances \class{}.
We abbreviate the classes
\Booleanlong{} to \Boolean{},
\Keywordlong{} to \Keyword{},
\NumberFull{} to \Number{},
\StringFull{} to \String{}, and
\FileFull{} to \File{}.
We also abbreviate the types
\EmptyUnion{} to \Bot{},
{\ValueNil} to \Nil{},
{\ValueTrue} to \True, and
{\ValueFalse} to {\False}.
%
The difference between the types
\Value{\class{}} and \class{} is subtle.
The former is inhabited by class literals like \Keyword{} and the result of
\appexp{\classconst{}}{\makekw{a}}---the latter by \emph{instances} of classes,
like a keyword literal \makekw{a}, an instance of the type \Keyword{}.
%
Function types
$
{\ArrowOne {\x{}} {\s{}}
{\t{}}
{\filterset {\prop{}} {\prop{}}}
{\object{}}}
$
contain \emph{latent} (terminology from~\cite{Lucassen88polymorphiceffect}) propositions \prop{}, object \object{}, and return type
\t{},
which may refer to the function argument \x{}.
%Latent means they are relevant when the function is applied rather than evaluated.
They are instantiated with the
actual object of the argument in applications. % before they are used in the proposition environment.
\paragraph{Objects}
%As we saw in \secref{sec:overview},
%occurrence typing is capable of reasoning
%about deeply nested expressions.
Each expression is associated with
a symbolic representation
called an \emph{object}.
%with respect to the current lexical environment.
For example,
variable \makelocal{m} has object \makelocal{m};
$\appexpone{\ccclass{\appexp{\makekw{lunch}}{\makelocal{m}}}}$ has object ${\pth{\classpe{}}{\pth{\keype{\makekw{lunch}}}{\makelocal{m}}}}$; and $42$ has the \emph{empty} object \emptyobject{} since it is unimportant in our system.
%
\figref{main:figure:termsyntax} gives the syntax for objects \object{}---non-empty objects
\pth{\pathelem{}}{\x{}} combine of a root variable \x{} and a \emph{path} \pathelem{},
which consists of
a possibly-empty sequence of \emph{path elements} (\pesyntax{}) applied right-to-left from the root variable.
We use two path elements---{\classpe{}} and {\keype{k}}---representing the results
of calling \classconst{} and looking up a keyword $k$, respectively.
\paragraph{Propositions with a logical system}
In standard type systems, association lists often
track the types of variables, like in LC-Let and LC-Local.
\begin{singlespacing}
\begin{mathpar}
\infer [LC-Let]
{ \judgementtwo {{\propenv{}}}
{\e{1}} {\s{}}
\\
\judgementtwo {{\propenv{}},\x{} \mapsto {\s{}}}
{\e{2}} {\t{}}
}
{
\judgementtwo {\propenv{}}
{\letexp{\x{}}{\e{1}}{\e{2}}} {\t{}}
}
\infer [LC-Local]
{ {\propenv{}}(\x{}) = {\t{}}
}
{ \judgementtwo {\propenv{}}
{\x{}} {\t{}}
}
\end{mathpar}
\end{singlespacing}
Occurrence typing instead pairs \emph{logical formulas},
that can reason about arbitrary non-empty objects,
with a \emph{proof system}.
The logical statement {\isprop{\s{}}{\x{}}} says
variable $x$ is of type \s{}.
%A \emph{logical system}
%must now \emph{prove}
%a variable's type.
\begin{singlespacing}
\begin{mathpar}
\infer [T0-Let]
{ \judgementtwo {{\propenv{}}}
{\e{1}} {\s{}}
\\
\judgementtwo {{\propenv{}},\isprop{\s{}}{\x{}}}
{\e{2}} {\t{}}
}
{
\judgementtwo {\propenv{}}
{\letexp{\x{}}{\e{1}}{\e{2}}}
{\t{}}
}
%\judgementtwo{\isprop{\Number{}}{\x{}}}{\appexp{\inc{}}{\x{}}}{\Number}
\infer [T0-Local]
{ \inpropenv {\propenv{}} {\isprop {\t{}} {\x{}}}}
{ \judgementtwo {\propenv{}}
{\x{}} {\t{}}
}
\end{mathpar}
\end{singlespacing}
In T0-Local,
$
{ \inpropenv {\propenv{}} {\isprop {\t{}}{\x{}}}}
$
appeals to the proof system to solve for \t{}.
%says under logical assumptions {\propenv{}}, object {\pth{\pathelem{}}{\x{}}} is of type \t{}.
%We later define the more general T-Local.
\begin{figure}[t!]
%\footnotesize
$$
\begin{array}{lrll}
\e{} &::=& \x{}
\alt \v{}
\alt {\comb {\e{}} {\e{}}}
\alt {\abs {\x{}} {\t{}} {\e{}}}
\alt {\ifexp {\e{}} {\e{}} {\e{}}}
%\alt {\trdiff{\doexp {\e{}} {\e{}}}}
\alt {\letexp {\x{}} {\e{}} {\e{}}}
%\alt {\errorvalv{}}
&\mbox{Expressions} \\
\v{} &::=& \singletonmeta{}
\alt {\nat{}}
\alt {\const{}}
\alt {\str{}}
\alt {\closure {\openv{}} {\abs {\x{}} {\t{}} {\e{}}}}
&\mbox{Values} \\
\constantssyntax{}\\
\s{}, \t{} &::=& \Top
\alt {\Unionsplice {\overrightarrow{\t{}}}}
\alt
{\ArrowOne {\x{}} {\t{}}
{\t{}}
{\filterset {\prop{}} {\prop{}}}
{\object{}}}
\alt {\Value \singletonmeta{}}
\alt \trdiff{\class{}}
&\mbox{Types} \\
\singletonallsyntax{}
\\ \\
\occurrencetypingsyntax{}\\
\propenvsyntax{}\\
\openvsyntax{}
%\\
%\classliteralallsyntax{}
\end{array}
$$
\caption{Syntax of Terms, Types, Propositions and Objects}
\label{main:figure:termsyntax}
\end{figure}
We further extend logical statements to \emph{propositional logic}.
\figref{main:figure:termsyntax} describes the syntax
for propositions \prop{},
consisting of positive and negative \emph{type propositions}
about non-empty objects---{\isprop {\t{}} {\pth {\pathelem{}} {\x{}}}}
and {\notprop {\t{}} {\pth {\pathelem{}} {\x{}}}}
respectively---the latter pronounced ``the object {\pth {\pathelem{}} {\x{}}} is \emph{not} of type \t{}''.
The other propositions are standard logical connectives: implications, conjunctions,
disjunctions, and the trivial (\topprop{}) and impossible (\botprop{}) propositions.
%
The full proof system judgement
$
{ \inpropenv {\propenv{}} {\prop{}} }
$
says \emph{proposition environment} {\propenv{}} proves proposition \prop{}.
Each expression is associated with two propositions---when expression
\e{1} is in test position like
\ifexp{\e{1}}{\e{2}}{\e{3}},
the type system extracts \e{1}'s `then' and `else' proposition to check
\e{2} and \e{3} respectively.
For example, in \ifexp{\makelocal{o}}{\e{2}}{\e{3}}
we learn variable {\makelocal{o}} is true in \e{2} via {\makelocal{o}}'s `then' proposition $\notprop{\falsy{}}{\makelocal{o}}$, and
that {\makelocal{o}} is false in \e{3} via {\makelocal{o}}'s `else' proposition $\isprop{\falsy{}}{\makelocal{o}}$.
To illustrate, recall \egref{example:desserts-on-meal}.
The parameter \makelocal{o} is of type $\Order$,
%by the annotation on $desserts$
written
{\isprop{\Order}{\makelocal{o}}}
as a proposition.
%
In the ${\makekw{combo}}$ method, we know
${\appexp{\makekw{Meal}}{\makelocal{o}}}$ is ${\makekw{combo}}$,
based on multimethod dispatch rules. This is written
{\isprop{\Value{\makekw{combo}}}{\pth{\keype{\makekw{Meal}}}{\makelocal{o}}}},
pronounced ``the ${\makekw{Meal}}$ path of variable \makelocal{o} is of type
{\Value{\makekw{combo}}}''.
%\paragraph{Logical system in action}
To attain the type of \makelocal{o},
we must solve for \t{} in
$
{ \inpropenv
{\propenv{}}
{\isprop {\t{}} {\makelocal{o}}}}
$,
under proposition environment
$
\propenv{} = {{\isprop{\Order}{\makelocal{o}}},
{\isprop{\Value{\makekw{combo}}}{\pth{\keype{\makekw{Meal}}}{\makelocal{o}}}}}
$
which deduces \t{} to be a {\makekw{combo}} meal.
The logical
system \emph{combines} pieces of type information to deduce more accurate types for lexical
bindings---this is explained in \secref{formalmodel:proofsystem}.
%The first insight about occurrence typing is that
%logical formulas
%can be used to represent type information about our programs
%by relating parts of the runtime environment to types
%via propositional logic.
%\emph{Type propositions} make assertions like ``variable \x{} is of type \NumberFull{}'' or
%``variable \x{} is not \nil{}''---in our logical system we write these as
%{\isprop{\NumberFull}{\x{}}}
%and {\notprop{\Nil{}}{\x{}}}.
%
%The second insight is that we can replace the traditional
%representation of a
%type environment (eg., a map from variables to types)
%with a set of propositions, written \propenv{}.
%Instead of mapping \x{} to
%the type \NumberFull{}, we use the proposition {\isprop{\NumberFull}{\x{}}}.
\begin{figure*}[t]
%\footnotesize
%{\TDo}
%{\TClass}
%{\TIf}
%{\TAbs}
%\begin{array}{c}
% {\TSubsume}\\\\
% {\TNum}
%\end{array}
\begin{mathpar}
{\TLocal}
{\TAbs}
{\TIf}
\\
\begin{array}{c}
{\TKw}\\
{\TNum}\\
\end{array}
\begin{array}{c}
{\TNil}\\
{\TFalse}\\
{\TConst}
\end{array}
\begin{array}{c}
{\TStr}\\
{\TClass}\\
{\TTrue}
\end{array}
\\
{\TLet}
\\
{\TApp}\ \
{\TSubsume}
\\
\end{mathpar}
%\begin{array}{c}
% {\TSubsume}\\\\
% {\TStr}\\\\
% {\TNil}\\\\
% {\TFalse}
%\end{array}
\caption{Core typing rules}
\label{main:figure:othertypingrules}
\end{figure*}
\begin{figure}%[t!]
%\footnotesize
\begin{mathpar}
\SUnionSuper{}\ \ \
\SUnionSub{}\ \ \
\SFunMono{}\ \ \
\begin{array}{l}
\SObject{}\\
\SClass{}\\
\SSBool{}
\end{array}
\SFun{}
\begin{array}{l}
\SRefl{}\ \ \
\STop{}\\
\SSKw{}
\end{array}
\end{mathpar}
\caption{Core subtyping rules}
\label{main:figure:subtyping}
\end{figure}
\begin{figure}
\begin{mathpar}
\BIfTrue{}
\BIfFalse{}
\end{mathpar}
\caption{Select core semantics}
\label{main:figure:coresemantics}
\end{figure}
\paragraph{Typing judgment}
We formalize our system following Tobin-Hochstadt and Felleisen \cite{TF10}.
%(with differences highlighted in $\trdiff{\text{blue}}$)
The typing judgment
$
{\judgementshowrewrite {\propenv}
{\e{}} {\t{}}
{\filterset {\thenprop {\prop{}}}
{\elseprop {\prop{}}}}
{\object{}}
{\ep{}}}
$
says expression \e{} rewrites to \ep{}, which
is of type \t{} in the
proposition environment $\propenv{}$, with
`then' proposition {\thenprop {\prop{}}}, `else' proposition {\elseprop {\prop{}}}
and object \object{}.
For ease of presentation, we omit \ep{} when it is easily inferred.
We write
{\judgementtworewrite{\propenv}{\e{}} {\t{}}{\ep{}}
to mean
{\judgementshowrewrite {\propenv}
{\e{}} {\t{}}
{\filterset {\thenprop {\propp{}}}
{\elseprop {\propp{}}}}
{\objectp{}}
{\ep{}}}
for some {\thenprop {\propp{}}}, {\elseprop {\propp{}}}
and {\objectp{}}.
%and abbreviate self rewriting judgements
%{\judgementrewrite {\propenv}
% {\e{}} {\t{}}
% {\filterset {\thenprop {\prop{}}}
% {\elseprop {\prop{}}}}
% {\object{}}
% {\e{}}}
%to
%{\judgementselfrewrite {\propenv}
% {\e{}} {\t{}}
% {\filterset {\thenprop {\prop{}}}
% {\elseprop {\prop{}}}}
% {\object{}}}.
\paragraph{Typing rules}
The core typing rules are
given as \figref{main:figure:othertypingrules}. We introduce
the interesting rules with the complement number predicate
as a running example.
\begin{equation}
\abs{\makelocal{d}}{\Top}{\ifexp{\appexp{\numberhuh{}}{\makelocal{d}}}{\false{}}{\true{}}}
\end{equation}
%, including
%a subsumption rule T-Subsume and rules for the false values---T-Nil and T-False---encoded
%as impossible (\botprop{}) `then' propositions.
The lambda rule T-Abs introduces \isprop{\s{}}{\x{}}} = \isprop{\Top}{\makelocal{d}}
to check the body.
With \propenv{} = \isprop{\Top}{\makelocal{d}},
T-If first checks the test \e{1} = {\appexp{\numberhuh{}}{\makelocal{d}}}
via the T-App rule, with three steps.
First, in T-App the operator \e{} = \numberhuh{} is checked with T-Const, which
uses
\constanttypeliteral{} (\figref{main:figure:constanttyping}, dynamic semantics in the supplemental material)
to type constants.
\numberhuh{} is a predicate over numbers, and
\classconst{} returns its argument's class.
Resuming {\appexp{\numberhuh{}}{\makelocal{d}}},
in T-App the operand \ep{} = \makelocal{d} is checked with
T-Local as
\begin{equation}
\judgementselfrewrite{\propenv{}}
{\makelocal{d}}
{\Top}
{\filterset{\notprop{\falsy}{\makelocal{d}}}
{\isprop{\falsy}{\makelocal{d}}}}
{\makelocal{d}}
\end{equation}
which encodes the type, proposition, and object information
about variables. The proposition {\notprop{\falsy}{\makelocal{d}}}
says ``it is not the case that variable {\makelocal{d}} is of type {\falsy}'';
{\isprop{\falsy}{\makelocal{d}}} says ``{\makelocal{d}} is of type {\falsy}''.
Finally, the T-App rule substitutes the operand's object \objectp{}
for the parameter \x{} in the latent type, propositions, and object. The proposition
{\isprop{\Number{}}{\makelocal{d}}} says ``{\makelocal{d}} is of type {\Number{}}'';
{\notprop{\Number{}}{\makelocal{d}}} says ``it is not the case that {\makelocal{d}}
is of type {\Number{}}''. The object {\makelocal{d}} is the symbolic representation
of what the expression {\makelocal{d}} evaluates to.
\begin{equation}
\judgementselfrewrite{\propenv{}}
{\appexp{\numberhuh{}}{\makelocal{d}}}
{\Boolean{}}
{\filterset{\isprop{\Number{}}{\makelocal{d}}}
{\notprop{\Number{}}{\makelocal{d}}}}
{\emptyobject{}}
\end{equation}
To demonstrate, the `then' proposition---in T-App {\replacefor {\thenprop{\prop{}}} {\objectp{}} {\x{}}}---substitutes
the latent `then' proposition of \constanttype{\numberhuh{}} with
\makelocal{d}, giving
{\replacefor {\isprop{\Number{}}{\x{}}} {\makelocal{d}} {\x{}}} =
{\isprop{\Number{}}{\makelocal{d}}}.
To check the branches of {\ifexp{\appexp{\numberhuh{}}{\makelocal{d}}}{\false{}}{\true{}}},
T-If
introduces \thenprop{\prop{1}} = \isprop{\Number{}}{\makelocal{d}}
to check \e{2} = {\false{}},
and \elseprop{\prop{1}} = \notprop{\Number{}}{\makelocal{d}}
to check
\e{3} = \true{}.
%
The branches are first checked with T-False and T-True respectively,
the T-Subsume premises
\inpropenv {\propenv{}, {\thenprop {\prop{}}}} {\thenprop {\propp{}}}
and
\inpropenv {\propenv{}, {\elseprop {\prop{}}}} {\elseprop {\propp{}}}
allow us to pick compatible propositions for both branches.
%$$
%\judgementselfrewrite{\propenv{},{\isprop{\Number{}}{\makelocal{d}}}}
% {\false{}}
% {\False{}}
% {\filterset{\botprop{}}
% {\topprop{}}}
% {\emptyobject{}}
%$$
$$
\begin{array}{c}
\judgementselfrewrite{\propenv{},{\isprop{\Number{}}{\makelocal{d}}}}
{\false{}}
{\Boolean{}}
{\filterset{\notprop{\Number{}}{\makelocal{d}}}
{\isprop{\Number{}}{\makelocal{d}}}}
{\emptyobject{}}
\\
\judgementselfrewrite{\propenv{},{\notprop{\Number{}}{\makelocal{d}}}}
{\true{}}
{\Boolean{}}
{\filterset{\notprop{\Number{}}{\makelocal{d}}}
{\isprop{\Number{}}{\makelocal{d}}}}
{\emptyobject{}}
\end{array}
$$
%to suit the T-If outputs \t{} = \Boolean{}, \thenprop{\prop{}}
%= {\notprop{\Number{}}{\makelocal{d}}}, \elseprop{\prop{}} = {\isprop{\Number{}}{\makelocal{d}}},
%and \object{} = {\emptyobject{}}.
%
%In T-Subsume, we can upcast \t{} = \False{} to \tp{} = \Boolean{} via the premise
%\issubtypein{}{\t{}}{\tp{}}.
%and
%\inpropenv {\propenv{}, {\elseprop {\prop{}}}} {\elseprop {\propp{}}}
%from
%{\elseprop {\prop{}}} = \topprop{} to {\elseprop {\propp{}}} = {\isprop{\Number{}}{\makelocal{d}}}.
Finally T-Abs assigns a type to the overall function:
$$
{\judgementselfrewrite{}{\abs{\makelocal{d}}{\Top}{\ifexp{\appexp{\numberhuh{}}{\makelocal{d}}}{\false{}}{\true{}}}}
{\ArrowOne {\makelocal{d}} {\Top{}}
{\Boolean{}}
{\filterset {\notprop{\Number{}}{\makelocal{d}}}
{\isprop{\Number{}}{\makelocal{d}}}}
{\emptyobject{}}}
{\filterset {\topprop{}}
{\botprop{}}}
{\emptyobject{}}}
$$
%The object \x{} over latent propositions \thenprop{\prop{}} and
%\elseprop{\prop{}}, latent object \object{}, and latent type \t{}. The
%actual argument object---\objectp{}---is substituted in at application by T-App.
%The T-App rule instantiates parameters---like \x{} in T-Abs---with their actual object.
%The expression {\appexp{\numberhuh{}}{\makelocal{d}}} replaces its parameter object with \
%\judgementselfrewrite{\isprop{\Top}{\makelocal{d}}}{\appexp{\numberhuh{}}{\makelocal{d}}}
% {\Boolean{}}
% {\filterset{\isprop{\Number{}}{\makelocal{d}}}
% {\notprop{\Number{}}{\makelocal{d}}}}
% {\emptyobject{}}
%The T-If refines each branch based on the test---a
%{\appexp{\numberhuh{}}{\makelocal{d}}} test introduces \isprop{\Number{}}{\makelocal{d}}
%for checking the `then' branch and \notprop{\Number{}}{\makelocal{d}}
%for checking the `else' branch.
%%Information from each branch is combined via subsumption for the overall type, propositions, and object.
%The T-Subsume rule
%For example
%$
%\judgementselfrewrite{\isprop{\Top}{\makelocal{d}}}
% {\ifexp{\appexp{\numberhuh{}}{\makelocal{d}}}{\false{}}{\true{}}}
% {\Boolean{}}
% {\filterset{\notprop{\Number{}}{\makelocal{d}}}
% {\isprop{\Number{}}{\makelocal{d}}}}
% {\emptyobject{}}
%$
%type checks because T-Subsume allows us to check both branches as
%$
%\judgementselfrewrite{\isprop{\Number{}}{\makelocal{d}}}
% {\false{}}
% {\Boolean{}}
% {\filterset{\notprop{\Number{}}{\makelocal{d}}}
% {\isprop{\Number{}}{\makelocal{d}}}}
% {\emptyobject{}}
%$
%and
%$
%\judgementselfrewrite{\notprop{\Number{}}{\makelocal{d}}}
% {\true{}}
% {\Boolean{}}
% {\filterset{\notprop{\Number{}}{\makelocal{d}}}
% {\isprop{\Number{}}{\makelocal{d}}}}
% {\emptyobject{}}
%$
%respectively.
%
%For example, if \e{2} is true when variable {\makelocal{y}} is a \File{}
%and \e{3} is true when variable {\makelocal{z}} is a \Number{}, then
%we use T-Subsume on both branches
%to introduce a logical disjunction
%since at least one must be true if the entire expression is true.
%Given a set of propositions, we can use logical reasoning to derive
%new information about our programs
%with the judgment \inpropenv{\propenv{}}{\prop{}}.
%In addition to the standard rules for the logical connectives, the key
%rule is L-Update, which combines multiple propositions about the same variable,
%allowing us to refine its type.
%$$
% {\LUpdate}
%$$
%For example, with L-Update we can use the knowledge of
%\inpropenv{\propenv{}}{\isprop{\UnionNilNum}{\x{}}}
%and
%\inpropenv{\propenv{}}{\notprop{\Nil{}}{\x{}}}
%to derive \inpropenv{\propenv{}}{\isprop{\Number}{\x{}}}.
%(The metavariable \propisnotmeta{} ranges over \t{} and \nottype{\t{}} (without variables).)
%We cover L-Update in more detail in \secref{sec:formalpaths}.
%
%Finally, this approach allows the type system to track
%programming idioms from
%dynamic languages
%using implicit type-based reasoning based on the result of
%conditional tests.
%For instance,
%\egref{example:parent-if}
%only utilizes \clj{f} once
%the programmer is convinced it is safe to do so based whether
%\clj{f}
%is
%true or false.
%To express this in the type system, every expression
%is described by two propositions: a `then' proposition
%for when it reduces to a true value, and an `else' proposition
%when it reduces to a false value---for \clj{f}
%the then proposition is {\notprop{\falsy}{f}} and
%the else proposition is {\isprop{\falsy}{f}}.
%\ref{main:figure:typingrules}
%\figref{main:figure:typingrules} contains the core typing rules.
%The key rule for reasoning about conditional control flow is
%T-If.
%
%\begin{mathpar}
% {\TIf}
%\end{mathpar}
%The propositions of the test expression \e{1}, \thenprop{\prop{1}} and \elseprop{\prop{1}}, are
%used as assumptions in the then and else branch respectively.
%The let rule T-Let links inferred information about
%\x{} to the expression used to instantiate \x{}, \ep{1}, via logical implications.
%
%The T-Local rule connects the type system to the proof system over type propositions
%via \inpropenv {\propenv{}} {\isprop {\t{}} {\x{}}}
%to derive a type for a variable.
%Using this rule, the type system can then appeal to L-Update to refine the type
%assigned to \x{}.
%
%We are now equipped to type check
%\egref{example:parent-if}:
%$$
%\clj{(if f (.getParent f) nil)}
%$$
%
%With {\propenv{}} = {\isprop{\UnionNilFile{}}{f}},
%$$
%\judgement{\propenv{}}{f}{\UnionNilFile{}}{\localfilterset{f}}{f}
%$$
%via T-Local.
%
%Checking the then branch involves extending
%the proposition environment with {\notprop{\falsy}{f}}
%$$
%\judgement{{\propenv{}},{\isprop{\Number}{\x{}}}}{\x{}}{\Number{}}{\filterset{\notprop{\falsy{}}{\x{}}}{\isprop{\falsy{}}{\x{}}}}{\emptyobject{}}
%$$
%because we can now satisfy the premise of T-Local:
%$$
%\inpropenv{{\propenv{}},\isprop{\Number}{\x{}}}{\isprop{\Number}{\x{}}}.
%$$
%\judgement{{\propenv{}},\isprop{\Number}{\x{}}}{\hastype{\appexp{\inc{}}{\x{}}}{\Number{}}}{\filterset{\topprop{}}{\botprop{}}}{\emptyobject{}}
%$$
%$$
%\judgement{{\propenv{}},\notprop{\Number}{\x{}}}{\hastype{\zeroliteral{}}{\Number}}{\filterset{\topprop{}}{\botprop{}}}{\emptyobject{}}
%$$
%\inc{} has type
%$$
%{\ArrowOne{\x{}}{\Number}{\Number}
% {\filterset{\topprop{}}{\topprop{}}}{\emptyobject{}}}
%$$
%We can now check the conditional with T-If.
%$$
%\judgement{\isprop{\Number}{\x{}}}{\hastype{\ifexp{\appexp{\numberhuh{}}{\x{}}}{\appexp{\inc{}}{\x{}}}{\zeroliteral{}}}{\Number}}{\filterset{\orprop{\isprop{\Number}{\x{}}}{\topprop{}}}{\orprop{\notprop{\Number}{\x{}}}{\topprop{}}}}{\emptyobject{}}
%$$
%Finally the function can be checked with T-Abs
%$$
%\judgement{}{\hastype{\abs{\x{}}{\UnionNilNum}{\ ...}}
% {\ArrowOne{\x{}}{\UnionNilNum}{\Number}
% {\filterset{\orprop{\isprop{\Number}{\x{}}}{\topprop{}}}{\orprop{\notprop{\Number}{\x{}}}{\topprop{}}}}{\emptyobject{}}}}
% {\filterset{\topprop{}}{\botprop{}}}{\emptyobject{}}
%$$
\paragraph{Subtyping}
\figref{main:figure:subtyping} presents subtyping
as a reflexive and transitive relation with top type \Top.
Singleton types are instances of their respective classes---boolean singleton types
are of type \Boolean{}, class literals are instances of \Class{} and keywords are
instances of \Keyword{}.
Instances of classes \class{} are subtypes of \Object{}. Function types
are subtypes of \IFn{}. All types except for \Nil{} are subtypes of \Object{},
so \Top{} is similar to {\Union{\Nil}{\Object}}.
Function subtyping is contravariant left of the arrow---latent propositions, object
and result type are covariant.
Subtyping for untagged unions is standard.
\paragraph{Operational semantics} We define the dynamic semantics for \lambdatc{}
in a big-step style using an environment, following~\cite{TF10}.
We include both errors and a \wrong{} value, which is provably ruled out by the
type system.
The main judgment is \opsem{\openv{}}{\e{}}{\definedreduction{}}
which states that \e{} evaluates to answer \definedreduction{} in environment
\openv{}. We chose to omit the core rules (included in supplemental material)
however a notable difference is \nil{} is a false value, which affects the
semantics of \ifliteral{} (\figref{main:figure:coresemantics}).
%The definition of \updateliteral{} supports various idioms relating to \classpe{}
%which we introduce in \secref{sec:isaformal}.
%\begin{figure*}
% \footnotesize
%%% \judgbox{
%%%{\judgementrewrite {\propenv}
%%% {\e{}} {\t{}}
%%% {\filterset {\thenprop {\prop{}}}
%%% {\elseprop {\prop{}}}}
%%% {\object{}}{\ep{}}}}
%%% {Under proposition environment $\propenv{}$,
%%% expression \e{} is of type \t{}
%%% with \\
%%%
%%%`then' proposition {\thenprop {\prop{}}}, `else' proposition {\elseprop {\prop{}}}
%%%and object \object{} and rewrites to \ep{}.}
% \begin{mathpar}
% %{\TDo}
% %{\TClass}
% %{\TIf}
% %{\TAbs}
% %\begin{array}{c}
% % {\TSubsume}\\\\
% % {\TNum}
% %\end{array}
% \begin{array}{c}
% {\TNum}\\\\
% {\TConst}\\\\
% {\TKw}\\\\
% {\TClass}\\\\
% {\TTrue}\\\\
% \end{array}
% \begin{array}{c}
% {\TSubsume}\\\\
% {\TNil}\\\\
% {\TFalse}
% \end{array}
%
% %{\TLet}
% %{\TLocal}
%
% %{\TApp}
% %{\TError}
%
% \end{mathpar}
% \caption{Typing rules}
% \label{main:figure:typingrules}
%\end{figure*}
%\begin{figure}
% \footnotesize
% \begin{mathpar}
% {\BLocal}
%
% %{\BDo}
%
% {\BLet}
%
% \BVal{}
%
%\BIfTrue{}
% \BIfFalse{}
%
% \BAbs{}
%
% \BBetaClosure{}
%
% \BDelta{}
% \end{mathpar}
% \caption{Operational Semantics}
% \label{main:figure:standardopsem}
%\end{figure}
%\subsection{Reasoning about Exceptional Control Flow}
%\label{sec:doformal}
%
%Along with conditional control flow,
%Clojure programmers rely on \emph{exceptions}
%to assert type-related invariants.
%
%\begin{exmp}
%\inputminted[firstline=13,lastline=15]{clojure}{code/demo/src/demo/do.clj}
%\label{example:doexception}
%\end{exmp}
%
%The fully expanded increment function in~\egref{example:doexception}
%guards its final call with a number check, preventing
%a possible null-pointer exception.
%Without this check, the type system would reject the program.
%
%To check this example,
%occurrence typing
%automatically
%assumes
%\clj{x} is a number when checking the second \clj{do} subexpression
%based on the first subexpression.
%\footnote{See \url{https://github.com/typedclojure/examples}
% for full examples.}
%We model this formally %(section~\ref{sec:doformal})
%and prove
%null-pointer exceptions are impossible in typed code (section~\ref{sec:metatheory}).
%
%
%We extend our model with sequencing expressions and errors, where {\errorvalv{}}
%models the result of calling Clojure's \clj{throw} special form
%with some \clj{Throwable}.
%
%\smallskip
%$
%\begin{altgrammar}
% \e{} &::=& \ldots \alt {\errorvalv{}} \alt {\doexp {\e{}} {\e{}}} &\mbox{Expressions}
%\end{altgrammar}
%$
%
%\smallskip
%%
%%B-Do simply evaluates its arguments sequentially and returns the right argument.
%%Since errors are not values, we define error propagation semantics
%%like BE-Do1 (figure~\ref{appendix:figure:errorstuck} for the full rules).
%%
%%\begin{mathpar}
%% {\BDo}
%%
%%\infer [BE-Error]
%%{}
%%{ \opsem {\openv{}}
%% {\errorvalv{}}
%% {\errorvalv{}}}
%%
%%\infer [BE-Do1]
%%{ \opsem {\openv{}} {\e{1}} {\errorvalv{}} }
%%{ \opsem {\openv{}} {\doexp{\e{1}}{\e{}}} {\errorvalv{}}}
%%\end{mathpar}
%
%Our main insight is as follows:
%if the first subexpression in a sequence reduces to a value, then it is either true or false.
%If we learn some proposition in both cases then we can use that proposition as an assumption to check the second subexpression.
%T-Do formalizes this intuition.
%
%\begin{mathpar}
% {\TDo}
%\end{mathpar}
%
%The introduction of errors,
%which do not evaluate to either
%a true or false value,
%makes our insight interesting.
%
%\begin{mathpar}
% {\TError}
%\end{mathpar}
%
%Recall \egref{example:doexception}.
%\begin{minted}{clojure}
%...
% (do (if (number? x) nil (throw (new Exception)))
% (inc x))
%...
%\end{minted}
%
%As before, checking \appexp{\numberhuh{}}{\x{}} allows us to use the proposition \isprop{\Number}{\x{}}
%when checking the then branch.
%
%By T-Nil and subsumption we can propagate this information to both propositions.
%$$
%\judgement{\isprop{\Number}{\x{}}}{\nil{}}{\Nil{}}{\filterset{\isprop{\Number}{\x{}}}{\isprop{\Number}{\x{}}}}{\emptyobject{}}
%$$
%Furthermore, using T-Error
%and subsumption we can conclude anything in the else branch.
%$$
%\judgement{\notprop{\Number}{\x{}}}{\errorvalv{}}{\Bot}{\filterset{\isprop{\Number}{\x{}}}{\isprop{\Number}{\x{}}}}{\emptyobject{}}
%$$
%Using the above as premises to T-If we conclude that if the first
%expression in the \doliteral{} evaluates successfully, \isprop{\Number}{\x{}} must be true.
%$$
%\judgement{\isprop{\UnionNilNum}{\x{}}}
% {\ifexp{\appexp{\numberhuh{}}{\x{}}}{\nil{}}{\errorvalv{}}}{\Boolean}
% {\filterset{\isprop{\Number}{\x{}}}{\isprop{\Number}{\x{}}}}{\emptyobject{}}
%$$
%We can now use \isprop{\Number}{\x{}} in the environment to check the second subexpression
%{\appexp{\inc{}}{\x{}}}, completing the example.
\section{Java Interoperability}
\begin{figure}
%\footnotesize
$$
\begin{altgrammar}
\e{} &::=& \ldots \alt {\fieldexp {\fld{}} {\e{}}} \alt {\methodexp {\mth{}} {\e{}} {\overrightarrow{\e{}}}}
\alt {\newexp {\class{}} {\overrightarrow{\e{}}}}
&\mbox{Expressions}\\
&\alt& \nonreflectiveexpsyntax{} &\mbox{Non-reflective Expressions}\\
\v{} &::=& \ldots \alt {\classvalue{\classhint{}} {\overrightarrow {\classfieldpair{\fld{}} {\v{}}}}}
&\mbox{Values} \\
\classtableallsyntax{}
\end{altgrammar}
$$
\begin{mathpar}
{\TNew}
{\TMethod}
{\TField}
%{\TInstance}
\end{mathpar}
%\classtablelookupsyntax{}
\begin{mathpar}
\begin{altgrammar}
\convertjavatypenil{}
\end{altgrammar}
\begin{altgrammar}
\convertjavatypenonnil{}
\end{altgrammar}
\begin{altgrammar}
\converttctype{}
\end{altgrammar}
\end{mathpar}
\begin{mathpar}
\BField{}\ \ \
%
\BNew{}
\BMethod{}
\end{mathpar}
\caption{Java Interoperability Syntax, Typing and Operational Semantics}
\label{main:figure:javatyping}
\end{figure}
\begin{figure}
$$
\constanttypefigure{}
$$
\caption{Constant typing}
\label{main:figure:constanttyping}
\end{figure}
We present Java interoperability in a restricted setting without class inheritance,
overloading or Java Generics.
%
We extend the syntax in \figref{main:figure:javatyping} with Java field lookups and calls to
methods and constructors.
To prevent ambiguity between zero-argument methods and fields,
we use Clojure's primitive ``dot'' syntax:
field accesses are written \fieldexp{\fld{}}{\e{}}
and method calls $\methodexp{\mth{}}{\e{}}{\overrightarrow{e}}$.
%and \clj{(new class es*)} is $\newexp{\class{}}{\overrightarrow{es}}$.
In \egref{example:getparent-direct-constructor}, \clj{(*interop .getParent (*interop new File "a/b" interop*) interop*)}
translates to
\begin{equation} \label{eq:unresolved}
\qquad {\methodexp {\getparent{}} {\newexp {\File{}} {\makestr{a/b}}} {}}
\end{equation}
But both the constructor and method are unresolved.
We introduce \emph{non-reflective} expressions for specifying exact Java overloads.
\begin{equation} \label{eq:resolved}
\qquad {\methodstaticexp {\File} {} {\String} {\getparent{}} {\newstaticexp {\String} {\File{}} {\File{}} {\makestr{a/b}}} {}}
\end{equation}
From the left, the one-argument constructor for \File takes a \String, and the
\getparent{} method of
\File{} takes zero arguments
and
returns a \String.
We now walk through this conversion.% from unresolved expression~\ref{eq:unresolved} to
%resolved expression~\ref{eq:resolved}.
\paragraph{Constructors} First we check and convert {\newexp {\File{}} {\makestr{a/b}}} to {\newstaticexp {\String} {\File{}} {\File{}} {\makestr{a/b}}}.
The T-New typing rule checks and rewrites constructors.
%$$
% {\TNew}
%$$
To check
{\newexp {\File{}} {\makestr{a/b}}}
we first resolve the constructor overload in the class table---there is at most one
to simplify presentation.
With \classhint{1} = \String,
we convert to a nilable type the argument with \t{1} = \Union{\Nil}{\String}
and type check {\makestr{a/b}} against \t{1}.
Typed Clojure defaults to allowing non-nilable arguments, but this
can be overridden, so we model the more general case.