Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove polymorphic variants using module namespacing #487

Closed
Closed
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
aa60c5b
Don't define recursive Sugartypes unless necessary
jstolarek Feb 19, 2019
25e9ff5
Redefine patterns as an ordinary variant datatype
jstolarek Feb 19, 2019
9b45f31
Rename types inside Pattern module
jstolarek Feb 20, 2019
b0f2428
Redefine iterpatt as an ordinary variant
jstolarek Feb 20, 2019
ec20de2
Redefine binding node as a variant
jstolarek Feb 20, 2019
eda5440
Prefix cp_phrasenodes constructors with CP
jstolarek Feb 20, 2019
3e5b598
Redefine phrasenode as a variant
jstolarek Feb 20, 2019
f9d483c
Redefine replace_rhs as a variant
jstolarek Feb 20, 2019
c5517d6
Redefine datatype as an ordinary variant
jstolarek Feb 20, 2019
08258e2
Redefine row_var as a variant
jstolarek Feb 20, 2019
70ab823
Remove unused logical_binope datatype
jstolarek Feb 20, 2019
013c10c
Redefine fieldspec as a variant
jstolarek Feb 20, 2019
2d8ce79
Redefine type_arg as a variant
jstolarek Feb 20, 2019
cf31b01
Rename sec datatype to section
jstolarek Feb 20, 2019
58daac4
Redefine section as a variant
jstolarek Feb 20, 2019
961c3d0
Redefine linearity as an ordinary variant
jstolarek Feb 20, 2019
2944102
Formatting only
jstolarek Feb 20, 2019
a9b6183
Wrap Sugartypes.ml to 80 lines
jstolarek Feb 20, 2019
3e7433a
Redefine unary operators as a variant
jstolarek Feb 20, 2019
a32e203
Redefine binary operators as a variant
jstolarek Feb 21, 2019
bbbdb04
Redefine restriction as a variant
jstolarek Feb 21, 2019
4f806cb
Refactor linearity and restriction functions
jstolarek Feb 21, 2019
7a6be88
Redefine declared linearity as a variant
jstolarek Feb 21, 2019
281aa5e
Documentation
jstolarek Feb 21, 2019
2b14409
Define primary kind as a variant
jstolarek Feb 21, 2019
a9304fd
Redefine location as a variant
jstolarek Feb 21, 2019
ac15a9a
Remove redundant code
jstolarek Feb 21, 2019
35691e7
Address @dhil's feedback
jstolarek Feb 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions bin/repl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ open Links_core
open Utility
open List
open Sugartypes
open CommonTypes

module BS = Basicsettings

Expand Down Expand Up @@ -227,11 +228,11 @@ let evaluate_parse_result envs parse_result =
| Some (finfo, _, None, location) ->
let v =
match location with
| `Server | `Unknown ->
| Location.Server | Location.Unknown ->
`FunctionPtr (var, None)
| `Client ->
| Location.Client ->
`ClientFunction (Js.var_name_binder (var, finfo))
| `Native -> assert false in
| Location.Native -> assert false in
let t = Var.info_type finfo in v, t
| _ -> assert false
in
Expand Down
9 changes: 5 additions & 4 deletions core/chaser.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
open Utility
open ModuleUtils
open Sugartypes

(* Helper functions *)
(* Helper function: given top-level module name, maps to expected filename *)
Expand Down Expand Up @@ -37,15 +38,15 @@ object(self)
{< shadow_table = shadow_table >}

method! bindingnode = function
| `QualifiedImport ns ->
| QualifiedImport ns ->
(* Try to resolve the import; if not, add to ICs list *)
let lookup_ref = List.hd ns in
(try
let _ = StringMap.find lookup_ref shadow_table in
self
with
_ -> self#add_import_candidate lookup_ref)
| `Module (n, bs) ->
| Module (n, bs) ->
let new_path = path @ [n] in
let fqn = lst_to_path new_path in
let o = self#bind_shadow n fqn in
Expand All @@ -71,7 +72,7 @@ let rec add_module_bindings deps dep_map =
| [module_name]::ys ->
(try
let (bindings, _) = StringMap.find module_name dep_map in
Sugartypes.with_dummy_pos (`Module (module_name, bindings)) :: (add_module_bindings ys dep_map)
with_dummy_pos (Module (module_name, bindings)) :: (add_module_bindings ys dep_map)
with Notfound.NotFound _ ->
(failwith (Printf.sprintf "Trying to find %s in dep map containing keys: %s\n"
module_name (print_list (List.map fst (StringMap.bindings dep_map))))));
Expand Down Expand Up @@ -109,7 +110,7 @@ let add_dependencies module_prog =
let sorted_deps = Graph.topo_sort_sccs deps in
(* Each entry should be *precisely* one element (otherwise we have cycles) *)
assert_no_cycles sorted_deps;
(* Now, build up binding list where each opened dependency is mapped to a `Module containing
(* Now, build up binding list where each opened dependency is mapped to a Module containing
* its list of inner bindings. *)
(* FIXME: This isn't reassigning positions! What we'll want is to retain the positions, but modify
* the position data type to keep track of the module filename we're importing from. *)
Expand Down
18 changes: 9 additions & 9 deletions core/checkXmlQuasiquotes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ let check mode pos e =

method! phrase = fun ({node=e; pos} as phrase) ->
match e with
| `Xml (_, _, _, children) ->
| Xml (_, _, _, children) ->
o#list (fun o -> o#phrase) children
| `FormBinding _ ->
| FormBinding _ ->
if mode <> `Formlet then
{< error = Some (`FormletBinding, pos) >}
else
super#phrase phrase
| `FormletPlacement _ ->
| FormletPlacement _ ->
if mode <> `Page then
{< error = Some (`FormletPlacement, pos) >}
else
super#phrase phrase
| `PagePlacement _ ->
| PagePlacement _ ->
if mode <> `Page then
{< error = Some (`PagePlacement, pos) >}
else
Expand Down Expand Up @@ -72,18 +72,18 @@ object (o)

method! phrase = fun ({node=e; pos} as phrase) ->
match e with
| `Xml _ when mode = `Quasi ->
| Xml _ when mode = `Quasi ->
super#phrase phrase
| `Xml _ when mode = `Exp ->
| Xml _ when mode = `Exp ->
check `Xml pos e;
o#phrase_with `Quasi phrase
| `Formlet (body, yields) when mode = `Exp ->
| Formlet (body, yields) when mode = `Exp ->
check `Formlet pos body.node;
(o#phrase_with `Quasi body)#phrase yields
| `Page body when mode = `Exp ->
| Page body when mode = `Exp ->
check `Page pos body.node;
o#phrase_with `Quasi body
| (`Formlet _ | `Page _) when mode = `Quasi ->
| (Formlet _ | Page _) when mode = `Quasi ->
(* The parser should prevent this from ever happening *)
raise (Errors.SugarError (pos, "Malformed quasiquote (internal error)"))
| _ when mode = `Quasi ->
Expand Down
7 changes: 4 additions & 3 deletions core/closures.ml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
open Utility
open CommonTypes

type freevars = {termvars: (Ir.binder list) ; typevars: Types.quantifier list} [@@deriving show]
type fenv = freevars IntMap.t [@@deriving show]
Expand Down Expand Up @@ -585,15 +586,15 @@ struct
let newvar = Types.fresh_raw_variable () in
let make_new_type_variable () = Unionfind.fresh (`Var (newvar, subkind, `Rigid)) in
let new_meta_var, updated_maps = match primary_kind with
| `Type ->
| PrimaryKind.Type ->
let new_type_variable = make_new_type_variable () in
let t = `MetaTypeVar new_type_variable in
(`Type new_type_variable, (IntMap.add typevar t type_map, row_map, presence_map))
| `Row ->
| PrimaryKind.Row ->
let new_type_variable = make_new_type_variable () in
let r = (Types.empty_field_env, new_type_variable, false) in
(`Row new_type_variable, (type_map, IntMap.add typevar r row_map, presence_map))
| `Presence ->
| PrimaryKind.Presence ->
let new_type_variable = make_new_type_variable () in
let p = `Var new_type_variable in
(`Presence new_type_variable, (type_map, row_map, IntMap.add typevar p presence_map)) in
Expand Down
111 changes: 111 additions & 0 deletions core/commonTypes.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
module Linearity = struct
type t = Any | Unl
[@@deriving eq,show]

let isAny lin = lin == Any
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
let isUnl lin = lin == Unl
jstolarek marked this conversation as resolved.
Show resolved Hide resolved

let string_of = function
| Any -> "Any"
| Unl -> "Unl"
end

(* Convenient aliases for constructing values *)
let linUnl = Linearity.Unl
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
let linAny = Linearity.Any
jstolarek marked this conversation as resolved.
Show resolved Hide resolved

module DeclaredLinearity = struct
type t = Lin | Unl
[@@deriving show]

let isLin lin = lin == Lin
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
let isUnl lin = lin == Unl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_unl

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let is_unl = function Unl -> true | _ -> false

end

(* Convenient aliases for constructing values *)
let dlLin = DeclaredLinearity.Lin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let declared_lin = ...

let dlUnl = DeclaredLinearity.Unl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let delcared_unl = ...


module Restriction = struct
type t =
| Any
| Base
| Session
| Effect
[@@deriving eq,show]

let isAny = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_any

| Any -> true
| _ -> false

let isBase = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_base

| Base -> true
| _ -> false

let isSession = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_session

| Session -> true
| _ -> false

let string_of = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_string

| Any -> "Any"
| Base -> "Base"
| Session -> "Session"
| Effect -> "Eff"
end

(* Convenient aliases for constructing values *)
let resAny = Restriction.Any
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're essentially introducing aliases for the more generically named variants like Any, by introducing linAny, resAny. In my opinion, this just shows that those constructors should be renamed. Effectively, only the aliases you define here are used in the rest of the code, so we could just rename the underlying constructors. What do the others think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only the aliases you define here are used in the rest of the code

To be more precise: only aliases are used for constructing values. For deconstructing them (pattern matching) we still use constructors, for these types usually with explicit qualification. As for renaming the constructors to ResAny, LinAny, etc. - because I understand that's what you're proposing - I wonder what others think. Sam criticized this as poor man's namespaces, so I went with modules. Perhaps a middle ground here is shortening the names of modules to Lin, DecLin, Res, PrKind? We could then remove the aliases because spelling out the module name wouldn't be that painful.

Rant: I wish OCaml had pattern synonyms.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I quite like the prefix, it is informative. But I wouldn't be opposed to the good ol' single letter prefix on constructor names either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res_any

let resBase = Restriction.Base
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res_base

let resSession = Restriction.Session
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res_session

let resEffect = Restriction.Effect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res_effect


module PrimaryKind = struct
type t =
| Type
| Row
| Presence
[@@deriving show,eq]

let string_of = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_string

| Type -> "Type"
| Row -> "Row"
| Presence -> "Presence"
end

(* Convenient aliases for constructing values *)
let pkType = PrimaryKind.Type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pk_type

let pkRow = PrimaryKind.Row
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pk_row

let pkPresence = PrimaryKind.Presence
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pk_presence


module Location = struct
type t = Client | Server | Native | Unknown
[@@deriving show]

let isClient = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_client

| Client -> true
| _ -> false

let isServer = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_server

| Server -> true
| _ -> false

let isNative = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_native

| Native -> true
| _ -> false

let isUnknown = function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_unknown

| Unknown -> true
| _ -> false

let string_of = function
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
| Client -> "client"
| Server -> "server"
| Native -> "native"
| Unknown -> "unknown"
end

(* Convenient aliases for constructing values *)
let locClient = Location.Client
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
let locServer = Location.Server
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
let locNative = Location.Native
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
let locUnknown = Location.Unknown
jstolarek marked this conversation as resolved.
Show resolved Hide resolved
64 changes: 33 additions & 31 deletions core/compilePatterns.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
to adjust our intermediate language.
*)

open CommonTypes
open Utility
open Ir

Expand Down Expand Up @@ -74,10 +75,10 @@ let lookup_name name (nenv, _tenv, _eff, _penv) =

let lookup_effects (_nenv, _tenv, eff, _penv) = eff

let rec desugar_pattern : Ir.scope -> Sugartypes.pattern -> pattern * raw_env =
let rec desugar_pattern : Ir.scope -> Sugartypes.Pattern.with_pos -> pattern * raw_env =
fun scope {Sugartypes.node=p; Sugartypes.pos} ->
let pp = desugar_pattern scope in
let empty = (NEnv.empty, TEnv.empty, Types.make_empty_open_row (`Any, `Any)) in
let desugar_pat = desugar_pattern scope in
let empty = (NEnv.empty, TEnv.empty, Types.make_empty_open_row (linAny, resAny)) in
let (++) (nenv, tenv, _) (nenv', tenv', eff') = (NEnv.extend nenv nenv', TEnv.extend tenv tenv', eff') in
let fresh_binder (nenv, tenv, eff) bndr =
assert (Sugartypes.binder_has_type bndr);
Expand All @@ -86,65 +87,66 @@ let rec desugar_pattern : Ir.scope -> Sugartypes.pattern -> pattern * raw_env =
let xb, x = Var.fresh_var (t, name, scope) in
xb, (NEnv.bind nenv (name, x), TEnv.bind tenv (x, t), eff)
in
let open Sugartypes.Pattern in
match p with
| `Any -> `Any, empty
| `Nil -> `Nil, empty
| `Cons (p, ps) ->
let p, env = pp p in
let ps, env' = pp ps in
| Any -> `Any, empty
| Nil -> `Nil, empty
| Cons (p, ps) ->
let p, env = desugar_pat p in
let ps, env' = desugar_pat ps in
`Cons (p, ps), env ++ env'
| `List [] -> pp (Sugartypes.with_pos pos `Nil)
| `List (p::ps) ->
let p, env = pp p in
let ps, env' = pp (Sugartypes.with_pos pos (`List ps)) in
| List [] -> desugar_pat (Sugartypes.with_pos pos Nil)
| List (p::ps) ->
let p, env = desugar_pat p in
let ps, env' = desugar_pat (Sugartypes.with_pos pos (List ps)) in
`Cons (p, ps), env ++ env'
| `Variant (name, None) -> `Variant (name, `Any), empty
| `Variant (name, Some p) ->
let p, env = pp p in
| Variant (name, None) -> `Variant (name, `Any), empty
| Variant (name, Some p) ->
let p, env = desugar_pat p in
`Variant (name, p), env
| `Effect (name, ps, k) ->
| Effect (name, ps, k) ->
let ps, env =
List.fold_right
(fun p (ps, env) ->
let p', env' = pp p in
let p', env' = desugar_pat p in
(p' :: ps, env ++ env'))
ps ([], empty)
in
let k, env' = pp k in
let k, env' = desugar_pat k in
`Effect (name, ps, k), env ++ env'
| `Negative names -> `Negative (StringSet.from_list names), empty
| `Record (bs, p) ->
| Negative names -> `Negative (StringSet.from_list names), empty
| Record (bs, p) ->
let bs, env =
List.fold_right
(fun (name, p) (bs, env) ->
let p, env' = pp p in
let p, env' = desugar_pat p in
StringMap.add name p bs, env ++ env')
bs
(StringMap.empty, empty) in
let p, env =
match p with
| None -> None, env
| Some p ->
let p, env' = pp p in
let p, env' = desugar_pat p in
Some p, env ++ env'
in
`Record (bs, p), env
| `Tuple ps ->
| Tuple ps ->
let bs = mapIndex (fun p i -> (string_of_int (i+1), p)) ps in
pp (Sugartypes.with_pos pos (`Record (bs, None)))
| `Constant constant ->
desugar_pat (Sugartypes.with_pos pos (Record (bs, None)))
| Constant constant ->
`Constant constant, empty
| `Variable b ->
| Variable b ->
let xb, env = fresh_binder empty b in
`Variable xb, env
| `As (b, p) ->
| As (b, p) ->
let xb, env = fresh_binder empty b in
let p, env' = pp p in
let p, env' = desugar_pat p in
`As (xb, p), env ++ env'
| `HasType (p, (_, Some t)) ->
let p, env = pp p in
| HasType (p, (_, Some t)) ->
let p, env = desugar_pat p in
`HasType (p, t), env
| `HasType (_, (_, None)) -> assert false
| HasType (_, (_, None)) -> assert false

type raw_bound_computation = raw_env -> computation
type bound_computation = env -> computation
Expand Down
Loading