Skip to content

Instantly share code, notes, and snippets.

@epost
Last active October 25, 2015 16:03
Show Gist options
  • Save epost/de87e67558a18de6716a to your computer and use it in GitHub Desktop.
Save epost/de87e67558a18de6716a to your computer and use it in GitHub Desktop.
haskell-ide model example 1

About

IDEs, and programming language tools in general, translate software facts (obtained from source code, library definitions, object files, etc.) and user input to other useful forms, such as editor or compiler actions, and diagrams. My proposal:

  • Separate queries and commands
    • query examples:
      • find location of definition of foo
      • find all locations that reference fromMaybe
      • find all possible completions at some location (e.g. my cursor): completions <FILE> <LINE> <COL>
    • command examples:
      • compile <FILE>
      • visit-location <FILE> <LINE> <COL>
  • Define a DSL for both
  • Specify the query and the software fact model that goes with it in terms of something well-understood. I opted for datalog here. Note that this does not mean that an implementation (e.g. haskell-ide) would have to use an actual generic datalog solver.
  • However, it should be capable of answering some subset of queries, and invoke editor commands based on their result(or vice versa. For example, it would be capable of answering the query ‘find location of definition of foo’, and invoke visit-location on its result.
  • The model could easily be reusable across (functional) languages: Haskell, Frege, PureScript, Elm, etc.

Try the knowledge base in Test1.prolog (which is really only datalog) by pasting it into the left pane here:

http://ysangkok.github.io/mitre-datalog.js/wrapper.html

Some example queries to try, in the pane on the right:

completions_for_module(X, test1)?

defined_at_loc(pure, U, L)?

used_at_loc(pure, F, R, C)?

doc(pure, URL)?

type_cons(X)?

defined_in_trans(X, maybe_mod)?
completions_for_module(X, test1)?
defined_at_loc(pure, U, L)?
used_at_loc(pure, F, R, C)?
doc(pure, URL)?
type_cons(X)?
defined_in_trans(X, maybe_mod)?
module Fnord.Zoink.Test1 where
import Data.Maybe
data Traffic = Red | Green
newtype Sum a = Sum a
f x = x + 1
% TODO add maybe type ctor, data cons
ident(test1, "Test1").
ident(zoink, "Zoink").
ident(traffic, "Traffic").
ident(sum_type_con, "Sum").
ident(sum_data_con, "Sum").
ident(f, "f").
ident(base, "base").
ident(frommaybe, "fromMaybe").
ident(isjust, "isJust").
ident(isnothing, "isNothing").
ident(maybe_type_con, "Maybe").
ident(maybe_mod, "Maybe").
ident(just, "Just").
ident(nothing, "Nothing").
module(test1).
module(zoink).
module(fnord).
module(data).
module(maybe_mod).
data(traffic).
data(maybe_data_con).
newtype(sum_type_con).
value(f).
value(frommaybe).
value(isjust).
value(isnothing).
value(pure).
value(ap).
data_con(red, traffic).
data_con(green, traffic).
data_con(sum_data_con, sum_type_con).
data_con(just, maybe_type_con).
data_con(nothing, maybe_type_con).
library(base).
defined_in(test1, zoink).
defined_in(zoink, fnord).
defined_in(traffic, test1).
defined_in(sum_type_con, test1).
defined_in(maybe_type_con, maybe_mod).
defined_in(f, test1).
defined_in(maybe_mod, data).
defined_in(maybe, base).
defined_in(frommaybe, maybe_mod).
defined_in(isjust, maybe_mod).
defined_in(isnothing, maybe_mod).
defined_in(applicative, control).
defined_in(applicative, base).
defined_in(pure, applicative).
defined_in(ap, applicative).
exported_by(frommaybe, maybe).
exported_by(isnothing, maybe).
exported_by(isjust, maybe).
exported_by(pure, applicative).
exported_by(ap, applicative).
imported_by(maybe, test1).
% file / web locations
defined_at_loc(pure, "https://github.com/ghc/packages-base/blob/master/Control/Applicative.hs", 115).
defined_at_loc(f, "https://hackage.haskell.org/package/base-4.8.1.0/docs/src/Data.Functor.html#%3C%24%3E").
doc(pure, "http://https://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#Applicative").
% usages
used_at_loc(pure, "src/Test2.hs", 13, 2).
used_at_loc(pure, "src/Test2.hs", 28, 8).
% rules
completions_for_module(X, M) :- value(X), imported_by_trans(X, M).
completions_for_module(X, M) :- value(X), defined_in(X, M).
type_con(X) :- data(X).
type_con(X) :- newtype(X).
defined_in_trans(X, Y) :- defined_in(X, Y).
defined_in_trans(X, Y) :- defined_in(X, Z), defined_in_trans(Z, Y).
imported_by_trans(X, M) :- imported_by(X, M).
imported_by_trans(X, M) :- exported_by(X, I), module(I), imported_by(I,M).
defined_in_trans(X, M) :- defined_in(X,M).
defined_in_trans(X, M) :- data_con(X,Y), defined_in(Y,M).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment