• No results found

Unbiased Skalpel does not prioritise any error that it reports over any other error, and so it is unbiased. The enumeration algorithm is responsible for this, as it con- tinues to search for unique errors when some have already been found. While some regions differently to others (e.g. end points of errors, which may be highlighted in another colour), no region is prioritised over any other region, and so also in that sense Skalpel is unbiased.

Comprehensive Skalpel presents all and only those pieces of code which are re- sponsible for an error, and so it follows that the user will never need to modify any code not presented by Skalpel in order to solve an error. For this reason, Skalpel is comprehensive in nature.

3.10

Other Implementations

Some of the authors of papers reviewed in chapter2have prepared implementations which are at least largely based on the work they have presented in their papers. This section aims to give an overview of some implementations that are currently available, whether they be simply improvements on algorithm W or more sophis- ticated implementations where for example type error corrections are suggested to the user.

The implementation of Goto and Sasano [GS12] can be found at the following URL1: http://www.cs.ise.shibaura-it.ac.jp/lambda-mode/

In this implementation the user writes their Standard ML code in Emacs (the implementation is an Emacs mode called Lambda-mode), as users of Skalpel are able to do, but rather than calling an external binary as Skalpel does, everything in this implementation is done in Emacs Lisp. A screenshot of what the software looks like can be seen in figure3.26.

While they gain the advantage that their software is extremely easy to install they tie their users to Emacs, so if the user doesn’t use that editor they will not be able to use the software. An advantage to implementing Skalpel in the current way is that users are not tied to any specific editor.

There are two implementations of type inference algorithms in this work, one is Milner’s type inference algorithm W [DM82], and the other is described as a type inference algorithm V, which was an algorithm created by the authors. The W

1 In the README located in the tarball at that location, Goto and Sassano invite users

to try sample programs located in the ‘sample’ folder, but this directory does not exist. It is recommended to enter the program shown in figure 8 of their paper as a sample program.

3.10. OTHER IMPLEMENTATIONS

Figure 3.26 Goto and Sasano Implementation

algorithm is used in the case of function applications, and in the case where there is a let expression which has a body (in the case where there is a let expression without a body the V algorithm is used).

In this implementation the way that candidates are checked whether they will make the code typable is that they are inserted into the code and then the unification algorithm is run with that candidate inserted. If unification succeeds, then this candidate is presented to the user, if it does not, then it is removed from the set of possible candidates2 that the user will be presented with. The authors essentially check for valid candidates in a similar way that the Skalpel analysis engine finds minimal type error slices. Each approach (ours and theirs) simply repeatedly run its own unification algorithm and looks at the results.

Another interesting implementation is that of Seminal, written in Ocaml, which detects type errors in untypable pieces of Ocaml code and provides suggestions to the user.

A basic example is shown here. Suppose the user has the basic program shown in figure3.27.

Figure 3.27 A simple ill-typed Ocaml program

1 let

2 c o n c a t F u n c t i o n s1 s2 = s1 ^ s2 3 in

4 p r i n t _ s t r i n g ( c o n c a t F u n c t i o n " hello , " 10)

This example is a simple case of a type error, as the user in this case has a function concatFunction which takes two strings and concatenates them together. In line 4 however, the user has mistakenly given concatFunction a string and an int as arguments.

2This can be seen in the enum-candidates-from-v-result-set and enum-candidates func-

3.10. OTHER IMPLEMENTATIONS

Figure3.28 shows the output of ocamlc without the use of seminal, and figure3.29

shows the output with Seminal output enabled.

Figure 3.28 Output of ocamlc for code in figure3.27

F i l e "/tmp/ t e s t . ml " , l i n e 4 , c h a r a c t e r s 40 −42:

T h i s e x p r e s s i o n has t y p e i n t but i s h e r e u s e d w i t h t y p e s t r i n g

Figure 3.29 Seminal output for code in figure3.27

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− F i l e "/tmp/ t e s t . ml " , l i n e 4 , c h a r a c t e r s 40 −42: T h i s e x p r e s s i o n has t y p e i n t but i s h e r e u s e d w i t h t y p e s t r i n g R e l e v a n t c o d e : 10 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− F i l e "/tmp/ t e s t . ml " , l i n e 2 , c h a r a c t e r s 30 −32: Try r e p l a c i n g s 2 w i t h s 1 o f t y p e s t r i n g w i t h i n c o n t e x t l e t c o n c a t F u n c t i o n s 1 s 2 = s 1 ^ s 1 i n ( p r i n t _ s t r i n g ( c o n c a t F u n c t i o n " h e l l o , " 1 0 ) ) ; ; ==============================

From these figures it be seen here that the compiler simply states that there is a type clash between int and string, on line 4 of the file, between characters 40 and 42. While the figure containing the Seminal output does not attempt to describe to the user precisely why this is an error (which is what Skalpel tries to do), it does make an effort to look at other lines and suggest changes that could be made. In this case, Seminal recommends that in line 2 of the code, s2 should be replaced by s1. This would indeed make the code typable.

There is no support for handling syntax errors in Seminal, so no suggestions are given for syntactic changes that the user might wish to make, and suggesting changes is available for type errors only.

The Seminal patch changes a few of the existing files in places (the Makefile, the configuration script and so on), but the bulk of the implementation comes in the form of a structure called Seminal. This is certainly desirable when implementing a system like this as a patch on compiler sources, if as little changes are made to the current compiler sources as possible then the less has to be changed when a new compiler release comes out and the code changes.

3.10. OTHER IMPLEMENTATIONS

The Seminal structure can be thought of as a function, with kinds of errors on the left hand side and options to try out to fix the error on the right hand side. The implementation seems to follow very closely what the paper describes. While the implementation for Seminal is not currently active, it is suspected that there would not be many changes needed in the implementation to make this work for the latest version of the Ocaml compiler.

Whether Skalpel would eventually be extended to give the user code suggestions as to what the user might change in order to fix their code is unknown at this time and outside the scope of this research project, but it is certainly an area for potential future work. It is an interesting aspect to consider however, as so much information is generated by Skalpel about the program that the user supplies already as it is. The Easy OCaml [EAS] implementation tarball can be downloaded from the below URL:

http://forge.ocamlcore.org/frs/download.php/94/easyocaml-0.49.tar.bz2 This tarball contains a patched version of the Ocaml compiler (reported to be version 3.10.2) in order to run EasyOCaml. A webdemo is also available at the following URL at this time of writing:

http://easyocaml.forge.ocamlcore.org/demo.php

The bulk of the implementation files for EasyOCaml can be found in the ocaml- 3.10.2/easyocaml/ subdirectory of the downloaded tarball. In here are a number of ML modules. A description of some of the more important ones is given here.

• ezyFeatures.ml. Contains many booleans allowing the user to restrict what feature set EasyOCaml is to handle. The below is a short extract of the file.

. . . . e_if_then : b o o l ; e _ i f _ t h e n _ e l s e : b o o l ; e _ l e t _ i n : l e t _ f e a t s o p t i o n ; e _ l e t _ r e c _ i n : l e t r e c _ f e a t s o p t i o n ; . . .

These flags would be enabled or disabled depending on the requested language feature set that is to be supported as specified by the user.

• ezyAst.ml. Contains the abstract syntax tree.

• ezyConstraints.ml. Somewhat comparable to the Env.sml implementation file present in Skalpel, which states how constraints can be used and manipulated.

3.10. OTHER IMPLEMENTATIONS

Also has some code which implements techniques from [HW03], such as ap- plying a derived environment to a type. A fragment of the code which handles this is given in figure 3.30.

Figure 3.30 Code extract showing application of derived environment to a type

l e t r e c apply_to_ty e t y = match t y w i t h | Ty . Var t y v a r −> b e g i n t r y l e t ty ’ , _ = TyVarMap . f i n d t y v a r e i n apply_to_ty e ty ’ w i t h Not_found −> t y end | Ty . C o n s t r ( l , k , t y s ) −> Ty . C o n s t r ( l , k , L i s t . map ( apply_to_ty e ) t y s ) | Ty . Tuple ( l , t y s ) −>

Ty . Tuple ( l , L i s t . map ( apply_to_ty e ) t y s ) | Ty . Arrow ( l , tx , tx ’ ) −>

Ty . Arrow ( l , apply_to_ty e tx , apply_to_ty e tx ’ )

• ezyTypingCoreTypes.ml. Comparable to the Ty.sml file in the Skalpel im- plementation which contains definitions for how constraints are represented. The type t is shown below:

t y p e t =

| Var o f TyVar . t

| Tuple o f E x t L o c a t i o n . t ∗ t l i s t

| C o n s t r o f E x t L o c a t i o n . t ∗ Path . t ∗ t l i s t | Arrow o f E x t L o c a t i o n . t ∗ t ∗ t

A TyVar.t is represented with an integer as shown below (some definitions at the bottom have been omitted with ‘...’ characters).

module TyVar : s i g t y p e t y v a r i n c l u d e P r i n t a b l e O r d e r e d T y p e w i t h t y p e t = t y v a r v a l f r e s h : u n i t −> t v a l i d : t −> i n t v a l none : t end = s t r u c t t y p e t y v a r = i n t t y p e t = t y v a r l e t c o u n t e r = r e f 0 l e t f r e s h ( ) = i n c r c o u n t e r ; ! c o u n t e r