commit f7d4d562278d6d9a0df134fdd77a1b2c644333bd
parent b54df0410d20da05e9dc5d064fe16ba62f9beff7
Author: Robert Russell <robertrussell.72001@gmail.com>
Date: Wed, 17 Jan 2024 19:58:39 -0800
Test a fix issue relating to quoted names
Diffstat:
| M | desugar.ml | | | 8 | ++++---- |
| M | elab.ml | | | 109 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
| M | error.ml | | | 114 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
| M | lexer.mll | | | 13 | +++++++------ |
| M | main.ml | | | 9 | ++++++--- |
| M | name.ml | | | 35 | +++++++++++++++++++++++++++++++---- |
| M | parser.mly | | | 106 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
| M | pretty.ml | | | 4 | ++-- |
8 files changed, 212 insertions(+), 186 deletions(-)
diff --git a/desugar.ml b/desugar.ml
@@ -1,13 +1,13 @@
open Util
open Node
-open Error
+module E = Error
module C = Concrete
module A = Abstract
let ensure_distinct names =
let declare name_set {loc; data = name} =
if Name.Var.Set.mem name name_set then
- abort loc (EDesugarDuplicateBinderName name)
+ E.abort loc (E.DesugarDuplicateBinderName name)
else
Name.Var.Set.add name name_set in
ignore @@ Array.fold_left declare Name.Var.Set.empty names
@@ -112,7 +112,7 @@ let rec term {loc; data = t} = match t with
| C.VariantType ctors ->
let insert m {loc = ctor_loc; data = C.Ctor (tag, doms)} =
if Name.Ctor.Map.mem tag.data m then
- abort tag.loc (EDesugarDuplicateCtor tag.data)
+ E.abort tag.loc (E.DesugarDuplicateCtor tag.data)
else
let ctor = ctor_loc @$ A.Ctor (Array.map domain doms) in
Name.Ctor.Map.add tag.data ctor m in
@@ -188,7 +188,7 @@ and discriminant names typs {loc; data = p} = match p with
| A.DWild, A.DWild -> loc @$ A.DWild
| A.DWild, A.DData _ -> qdisc
| A.DData _, A.DWild -> pdisc
- | A.DData _, A.DData _ -> abort loc EDesugarDataAndData
+ | A.DData _, A.DData _ -> E.abort loc E.DesugarDataAndData
end
| C.POr _ -> no_impl "or patterns"
| C.PParen p -> discriminant names typs p
diff --git a/elab.ml b/elab.ml
@@ -1,6 +1,6 @@
open Util
open Node
-open Error
+module E = Error
open Eval
open Quote
open Unify
@@ -19,8 +19,8 @@ type mode =
| Check of V.value
(* Convention: An elaboration-related function can have two versions, one whose
- * name ends with a prime, which can throw an Exn, and one whose name does not
- * end with a prime, which returns in the result monad.
+ * name ends with a prime, which can throw an E.Exn, and one whose name does
+ * not end with a prime, which returns in the result monad.
* TODO: Make sure every function has both versions, even if unused? *)
(* TODO: We check for name distinctness in two places; unify them. *)
@@ -28,7 +28,7 @@ let declare_name'
: Name.Var.Set.t -> Name.Var.t node -> Name.Var.Set.t
= fun name_set {loc; data = name} ->
if Name.Var.Set.mem name name_set then
- abort loc @@ EElabDuplicateName name
+ E.abort loc @@ E.ElabDuplicateName name
else
Name.Var.Set.add name name_set
@@ -79,7 +79,7 @@ let elaborate_args'
| Plicity.Ex ->
let j = i - !implicit_count in
begin if explicit_count <= j then
- abort loc EElabArityMismatch
+ E.abort loc E.ElabArityMismatch
end;
Some (explicit_args.(j))
| Plicity.Im ->
@@ -89,26 +89,26 @@ let elaborate_args'
(* We had enough explicit args, but now ensure we don't have too many. *)
begin if explicit_count > arity - !implicit_count then
- abort loc EElabArityMismatch
+ E.abort loc E.ElabArityMismatch
end;
args
let rec infer
-: context -> A.term -> (I.term * V.value, error) result
+: context -> A.term -> (I.term * V.value, E.error) result
= fun ctx t ->
try Ok (infer' ctx t) with
- | Exn e -> Error e
+ | E.Exn e -> Error e
and infer'
: context -> A.term -> I.term * V.value
= fun ctx t -> elaborate' ctx t Infer
and check
-: context -> A.term -> V.value -> (I.term, error) result
+: context -> A.term -> V.value -> (I.term, E.error) result
= fun ctx t vtyp ->
try Ok (check' ctx t vtyp) with
- | Exn e -> Error e
+ | E.Exn e -> Error e
and check'
: context -> A.term -> V.value -> I.term
@@ -117,10 +117,10 @@ and check'
t
and elaborate
-: context -> A.term -> mode -> (I.term * V.value, error) result
+: context -> A.term -> mode -> (I.term * V.value, E.error) result
= fun ctx t mode ->
try Ok (elaborate' ctx t mode) with
- | Exn e -> Error e
+ | E.Exn e -> Error e
and elaborate'
: context -> A.term -> mode -> I.term * V.value
@@ -153,7 +153,7 @@ and elaborate'
let (args, clo) = check_args' ctx loc explicit_args clo multibinder in
let vcodomain = eval clo codomain in
(I.App (fn, args), vcodomain)
- | vtyp -> abort loc @@ EElabApplyNonFunction (quote ctx.env vtyp)
+ | vtyp -> E.abort loc @@ E.ElabApplyNonFunction (quote ctx.env vtyp)
end
| A.Fn (params, body), Infer ->
@@ -168,7 +168,7 @@ and elaborate'
let {I.multibinder = {binders = domains; order}; I.codomain} = fntype in
begin if Array.length params <> Array.length domains then
- abort loc EElabFnArityMismatch
+ E.abort loc E.ElabFnArityMismatch
end;
let arity = Array.length params in
@@ -189,7 +189,7 @@ and elaborate'
end;
begin if param.plicity <> domain.plicity then
- abort loc EElabFnPlicityMismatch
+ E.abort loc E.ElabFnPlicityMismatch
end;
let plicity = param.plicity in
@@ -208,14 +208,14 @@ and elaborate'
(I.Fn {multibinder = {binders = params'; order}; body; codomain}, vfntype)
-(*| A.Fn _, Check vtyp -> abort loc @@ ErrExpectedFnType vtyp*)
+(*| A.Fn _, Check vtyp -> E.abort loc @@ ErrExpectedFnType vtyp*)
| A.FnType (domains, codomain), Infer ->
let (ctx, multibinder) = infer_multibinder' ctx loc domains in
let codomain = check' ctx codomain V.Type in
(I.FnType {multibinder; codomain}, V.Type)
-| A.Data _, Infer -> abort loc EElabCantInferData
+| A.Data _, Infer -> E.abort loc E.ElabCantInferData
| A.Data ({data = tag; _}, explicit_args),
Check (V.DataTypeClosure (clo, datatype) as vdatatype) ->
@@ -225,10 +225,10 @@ and elaborate'
datatype.ctors.(tagi) in
let datatype = quote_datatype ctx.env clo datatype in
(I.Data {tag; tagi; args; datatype}, vdatatype)
- | None -> abort loc @@ EElabUnexpectedCtor tag
+ | None -> E.abort loc @@ E.ElabUnexpectedCtor tag
end
-(*| A.Data _, Check vtyp -> abort loc @@ ErrExpectedDataType vtyp*)
+(*| A.Data _, Check vtyp -> E.abort loc @@ ErrExpectedDataType vtyp*)
| A.DataType ctors, Infer ->
let next = ref 0 in
@@ -248,7 +248,7 @@ and elaborate'
begin match Ctx.lookup ctx name i with
| Some {typ = V.Future (id, j); _} -> raise (BlockedOnFuture (id, j, name))
| Some {typ; value; _} -> (quote ctx.env value, typ)
- | None -> abort loc @@ EElabUnboundVar (name, i)
+ | None -> E.abort loc @@ E.ElabUnboundVar (name, i)
end
| A.Type, Infer -> (I.Type, V.Type)
@@ -261,7 +261,7 @@ and elaborate'
else
let expected = quote ctx.env vexpected in
let inferred = quote ctx.env vinferred in
- abort loc @@ EElabUnifyFail (expected, inferred)
+ E.abort loc @@ E.ElabUnifyFail (expected, inferred)
(* Check the given explicit arguments against the given multibinder.
* Return the elaborated terms and the multibinder's closure extended with
@@ -322,12 +322,12 @@ and infer_definers'
| Ok (names, vtyp) ->
let rhs = check' ctx rhs vtyp in
(names, rhs, vtyp)
- | Error {data = EElabNonInferablePatt; _} ->
+ | Error {data = E.ElabNonInferablePatt; _} ->
(* Next try to infer from rhs (and check lhs). *)
let (rhs, vtyp) = infer' ctx rhs in
let names = check_irrefutable_patt' ctx lhs vtyp in
(names, rhs, vtyp)
- | Error e -> abort e.loc e.data in
+ | Error e -> E.abort e.loc e.data in
let typ = quote ctx.env vtyp in
(* XXX: vrhs doesn't need to be a Rec. We could eagerly evaluate it, or
* add some other mechanism for laziness (like glued eval). *)
@@ -360,9 +360,9 @@ and infer_definers'
names vtyp (V.Arb (Uniq.get vars i)) in
ctx_with_asns := ctx';
asns.(i) <- asn
- | Error ({data = EElabNonInferablePatt; _} as root) ->
- abort loc @@ EElabNoLetAnnot root
- | Error e -> abort e.loc e.data
+ | Error ({data = E.ElabNonInferablePatt; _} as root) ->
+ E.abort loc @@ E.ElabNoLetAnnot root
+ | Error e -> E.abort e.loc e.data
done;
let ctx = !ctx_with_asns in
@@ -561,7 +561,7 @@ and infer_multibinder'
};
order.(j) <- i
| Pending _ ->
- abort loc @@ EElabBinderCycle (find_cycle states i)
+ E.abort loc @@ E.ElabBinderCycle (find_cycle states i)
done;
(ctx, {binders = binders'; order})
@@ -577,14 +577,14 @@ and infer_binder'
| None ->
match infer_irrefutable_patt ctx patt, plicity with
| Ok (_, vtyp), _ -> vtyp
- | Error {data = EElabNonInferablePatt; _}, Plicity.Im ->
+ | Error {data = E.ElabNonInferablePatt; _}, Plicity.Im ->
begin match check_irrefutable_patt ctx patt V.Type with
| Ok _ -> V.Type
- | Error root -> abort loc @@ EElabUnannotImplicitIsType root
+ | Error root -> E.abort loc @@ E.ElabUnannotImplicitIsType root
end
- | Error ({data = EElabNonInferablePatt; _} as root), Plicity.Ex ->
- abort loc @@ EElabNoBinderAnnot root
- | Error e, _ -> abort e.loc e.data
+ | Error ({data = E.ElabNonInferablePatt; _} as root), Plicity.Ex ->
+ E.abort loc @@ E.ElabNoBinderAnnot root
+ | Error e, _ -> E.abort e.loc e.data
(* Check that each term in the array starting at the given index is a type
* convertible to the given value. *)
@@ -597,47 +597,42 @@ and check_types'
begin if not (conv ctx.env vtyp vtyp') then
let typ = quote ctx.env vtyp in
let typ' = quote ctx.env vtyp' in
- abort typs.(i).loc @@ EElabUnifyFail (typ, typ')
+ E.abort typs.(i).loc @@ E.ElabUnifyFail (typ, typ')
end
done
and infer_irrefutable_patt
-: context -> A.patt -> (Name.Var.t node array * V.value, error) result
+: context -> A.patt -> (Name.Var.t node array * V.value, E.error) result
= fun ctx patt ->
try Ok (infer_irrefutable_patt' ctx patt) with
- | Exn e -> Error e
+ | E.Exn e -> Error e
-(* TODO: Reimplement with infer_patt'? *)
and infer_irrefutable_patt'
: context -> A.patt -> Name.Var.t node array * V.value
-= fun ctx {loc; data = patt} -> match patt with
-| {typs = [||]; _} -> abort loc EElabNonInferablePatt
-| {disc = {loc; data = A.DData _}; _} -> abort loc EElabDataPattRefutable
-| {names; typs; disc = {data = A.DWild; _}} ->
- let typ = check' ctx typs.(0) V.Type in
- let vtyp = eval ctx.env typ in
- check_types' ctx typs 1 vtyp;
- (names, vtyp)
+= fun ctx ({loc; _} as patt) ->
+ let (patt, vtyp) = infer_patt' ctx patt in
+ match patt with
+ | {disc = I.DData _; _} -> E.abort loc E.ElabDataPattRefutable
+ | {names; disc = I.DWild} -> (names, vtyp)
and check_irrefutable_patt
-: context -> A.patt -> V.value -> (Name.Var.t node array, error) result
+: context -> A.patt -> V.value -> (Name.Var.t node array, E.error) result
= fun ctx patt vtyp ->
try Ok (check_irrefutable_patt' ctx patt vtyp) with
- | Exn e -> Error e
+ | E.Exn e -> Error e
-(* TODO: Reimplement with check_patt'? *)
and check_irrefutable_patt'
: context -> A.patt -> V.value -> Name.Var.t node array
-= fun ctx {loc; data = patt} vtyp -> match patt with
-| {disc = {loc; data = A.DData _}; _} -> abort loc EElabDataPattRefutable
-| {names; typs; disc = {data = A.DWild; _}} ->
- check_types' ctx typs 0 vtyp;
- names
+= fun ctx ({loc; _} as patt) vtyp ->
+ let patt = check_patt' ctx patt vtyp in
+ match patt with
+ | {disc = I.DData _; _} -> E.abort loc E.ElabDataPattRefutable
+ | {names; disc = I.DWild} -> names
and infer_patt'
: context -> A.patt -> I.patt * V.value
= fun ctx {loc; data = patt} -> match patt with
-| {typs = [||]; _} -> abort loc EElabNonInferablePatt
+| {typs = [||]; _} -> E.abort loc E.ElabNonInferablePatt
| {names; typs; disc} ->
let typ = check' ctx typs.(0) V.Type in
let vtyp = eval ctx.env typ in
@@ -686,9 +681,9 @@ and check_disc'
I.DData {tag; tagi; subpatts = subpatts'; datatype}
- | None -> abort loc @@ EElabUnexpectedCtor tag
+ | None -> E.abort loc @@ E.ElabUnexpectedCtor tag
end
-| A.DData _, vtyp -> abort loc @@ EElabExpectedDataType (quote ctx.env vtyp)
+| A.DData _, vtyp -> E.abort loc @@ E.ElabExpectedDataType (quote ctx.env vtyp)
@@ -757,7 +752,7 @@ let rec elaborate_match loc scrutinee cases =
let switch = elaborate_switch loc used_cases env clauses in
begin match Array.find_index not used_cases with
(* TODO: Use loc of the redundant case, not the entire match. *)
- | Some i -> abort loc ErrRedundantCase
+ | Some i -> E.abort loc ErrRedundantCase
| None -> ()
end;
@@ -796,7 +791,7 @@ and elaborate_switch match_loc used_cases env clauses =
I.Switch (index, subswitches)
else
(* TODO: Give an example of a missing case. *)
- abort match_loc ErrNonExhaustiveMatch
+ E.abort match_loc ErrNonExhaustiveMatch
and elaborate_switch_branch match_loc used_cases env clauses var arity i =
let clause_count = Array.length clauses in
diff --git a/error.ml b/error.ml
@@ -4,92 +4,92 @@ module I = Internal
type error = error' node
and error' =
-| ELexerNameIndexTooBig
-| ELexerInvalidNumberTerminator
-| ELexerNoRule
+| LexerNameIndexTooBig
+| LexerInvalidNumberTerminator
+| LexerNoRule
-| EParserInvalidTerm
-| EParserInvalidPatt
-| EParserEmptyDomain
+| ParserInvalidTerm
+| ParserInvalidPatt
+| ParserEmptyDomain
-| EDesugarDuplicateCtor of Name.Ctor.t
-| EDesugarDuplicateBinderName of Name.Var.t
-| EDesugarDataAndData
+| DesugarDuplicateCtor of Name.Ctor.t
+| DesugarDuplicateBinderName of Name.Var.t
+| DesugarDataAndData
-| EElabApplyNonFunction of I.term
-| EElabNonInferablePatt
-| EElabUnifyFail of I.term * I.term (* TODO: Rename to ConvFail? *)
-| EElabUnexpectedCtor of Name.Ctor.t
-| EElabExpectedDataType of I.term
-| EElabNoLetAnnot of error
-| EElabBinderCycle of Name.Var.t list
-| EElabUnannotImplicitIsType of error
-| EElabNoBinderAnnot of error
-| EElabDuplicateName of Name.Var.t
-| EElabArityMismatch
-| EElabCantInferData
-| EElabDataPattRefutable
-| EElabUnboundVar of Name.Var.t * int
-| EElabFnArityMismatch
-| EElabFnPlicityMismatch
-(*| EElabNonExhaustiveMatch*)
-(*| EElabRedundantCase*)
-(*| EElabExpectedFnType of I.term*)
+| ElabApplyNonFunction of I.term
+| ElabNonInferablePatt
+| ElabUnifyFail of I.term * I.term
+| ElabUnexpectedCtor of Name.Ctor.t
+| ElabExpectedDataType of I.term
+| ElabNoLetAnnot of error
+| ElabBinderCycle of Name.Var.t list
+| ElabUnannotImplicitIsType of error
+| ElabNoBinderAnnot of error
+| ElabDuplicateName of Name.Var.t
+| ElabArityMismatch
+| ElabCantInferData
+| ElabDataPattRefutable
+| ElabUnboundVar of Name.Var.t * int
+| ElabFnArityMismatch
+| ElabFnPlicityMismatch
+(*| ElabNonExhaustiveMatch*)
+(*| ElabRedundantCase*)
+(*| ElabExpectedFnType of I.term*)
-let rec pp_print_error ppf {loc; data = e} =
+let rec pp_print ppf {loc; data = e} =
F.fprintf ppf "[%a] %a"
Loc.pp_print loc
- pp_print_error' e
+ pp_print' e
-and pp_print_error' ppf = function
-| ELexerNameIndexTooBig ->
+and pp_print' ppf = function
+| LexerNameIndexTooBig ->
F.pp_print_string ppf "name index too big"
-| ELexerInvalidNumberTerminator ->
+| LexerInvalidNumberTerminator ->
F.pp_print_string ppf "invalid character after number literal"
-| ELexerNoRule ->
+| LexerNoRule ->
F.pp_print_string ppf "lexical error"
-| EParserInvalidTerm ->
+| ParserInvalidTerm ->
F.pp_print_string ppf "invalid term"
-| EParserInvalidPatt ->
+| ParserInvalidPatt ->
F.pp_print_string ppf "invalid pattern"
-| EParserEmptyDomain ->
+| ParserEmptyDomain ->
F.pp_print_string ppf "empty domain"
-| EDesugarDuplicateCtor tag ->
+| DesugarDuplicateCtor tag ->
F.fprintf ppf "%s: %a"
"duplicate constructor: "
Name.Ctor.pp_print tag
-| EDesugarDuplicateBinderName name ->
+| DesugarDuplicateBinderName name ->
F.fprintf ppf "%s: %a"
"duplicate binder name: "
Name.Var.pp_print name
-| EDesugarDataAndData ->
+| DesugarDataAndData ->
F.pp_print_string ppf "conjunction of two data patterns"
-| EElabApplyNonFunction typ ->
+| ElabApplyNonFunction typ ->
F.fprintf ppf "@[<4>%s@ %a@]"
"attempt to apply non-function of inferred type"
(Pretty.pp_print_term 0) typ
-| EElabNonInferablePatt ->
+| ElabNonInferablePatt ->
F.pp_print_string ppf "non-inferable pattern"
(* TODO *)
-| EElabUnifyFail _ -> F.pp_print_string ppf "ErrUnifyFail"
-| EElabCantInferData -> F.pp_print_string ppf "ErrCantInferData"
-| EElabNoLetAnnot _ -> F.pp_print_string ppf "ErrNoLetAnnot"
-| EElabNoBinderAnnot _ -> F.pp_print_string ppf "ErrNoBinderAnnot"
-| EElabUnannotImplicitIsType _ -> F.pp_print_string ppf "ErrUnannotImplicitIsType"
-| EElabDataPattRefutable -> F.pp_print_string ppf "ErrDataPattRefutable"
-| EElabBinderCycle _ -> F.pp_print_string ppf "ErrBinderCycle"
-| EElabArityMismatch -> F.pp_print_string ppf "ErrArityMismatch"
-| EElabUnboundVar _ -> F.pp_print_string ppf "ErrUnboundVar"
-| EElabExpectedDataType _ -> F.pp_print_string ppf "ErrExpectedDataType"
-| EElabFnArityMismatch -> F.pp_print_string ppf "ErrFnArityMismatch"
-| EElabFnPlicityMismatch -> F.pp_print_string ppf "ErrFnPlicityMismatch"
-| EElabUnexpectedCtor _ -> F.pp_print_string ppf "ErrUnexpectedCtor"
-| EElabDuplicateName _ -> F.pp_print_string ppf "ErrDuplicateName"
-(*| EElabExpectedFnType _ -> "ErrExpectedFnType"*)
+| ElabUnifyFail _ -> F.pp_print_string ppf "ErrUnifyFail"
+| ElabCantInferData -> F.pp_print_string ppf "ErrCantInferData"
+| ElabNoLetAnnot _ -> F.pp_print_string ppf "ErrNoLetAnnot"
+| ElabNoBinderAnnot _ -> F.pp_print_string ppf "ErrNoBinderAnnot"
+| ElabUnannotImplicitIsType _ -> F.pp_print_string ppf "ErrUnannotImplicitIsType"
+| ElabDataPattRefutable -> F.pp_print_string ppf "ErrDataPattRefutable"
+| ElabBinderCycle _ -> F.pp_print_string ppf "ErrBinderCycle"
+| ElabArityMismatch -> F.pp_print_string ppf "ErrArityMismatch"
+| ElabUnboundVar _ -> F.pp_print_string ppf "ErrUnboundVar"
+| ElabExpectedDataType _ -> F.pp_print_string ppf "ErrExpectedDataType"
+| ElabFnArityMismatch -> F.pp_print_string ppf "ErrFnArityMismatch"
+| ElabFnPlicityMismatch -> F.pp_print_string ppf "ErrFnPlicityMismatch"
+| ElabUnexpectedCtor _ -> F.pp_print_string ppf "ErrUnexpectedCtor"
+| ElabDuplicateName _ -> F.pp_print_string ppf "ErrDuplicateName"
+(*| ElabExpectedFnType _ -> "ErrExpectedFnType"*)
exception Exn of error
diff --git a/lexer.mll b/lexer.mll
@@ -1,13 +1,13 @@
{
open Node
-open Error
+module E = Error
open Parser
let abort lexbuf e =
let beg_pos = Lexing.lexeme_start_p lexbuf in
let end_pos = Lexing.lexeme_end_p lexbuf in
let loc = Loc.of_positions beg_pos end_pos in
- Error.abort loc e
+ E.abort loc e
}
let ascii_horizontal = ['\t' ' '-'~']
@@ -31,9 +31,10 @@ let greek = ugreek | lgreek | lgreekalt
let comment = '\\' '\\' (ascii_horizontal | greek)*
+(* Keep in sync with non_start and non_cont in name.ml. *)
let ident_start = latin | greek | '_'
let ident_cont = latin | greek | '_' | dnumeral | '\'' | '"'
-let ident_quote = ascii_horizontal | greek
+let ident_quote = (ascii_horizontal # '`') | greek
let name = (ident_start ident_cont* as x) | '`' (ident_quote* as x) '`'
let tag = (ident_cont+ as x) | '`' (ident_quote* as x) '`'
@@ -110,15 +111,15 @@ rule token = parse
if Z.fits_int z then
INDEXED_NAME (x, Z.to_int z)
else
- abort lexbuf ELexerNameIndexTooBig
+ abort lexbuf E.LexerNameIndexTooBig
}
| name { NAME x }
| number as n { NAT (Z.of_string n) }
| number invalid_number_terminator
- { abort lexbuf ELexerInvalidNumberTerminator }
+ { abort lexbuf E.LexerInvalidNumberTerminator }
-| _ { abort lexbuf ELexerNoRule }
+| _ { abort lexbuf E.LexerNoRule }
{
}
diff --git a/main.ml b/main.ml
@@ -11,7 +11,6 @@ let buf = Lexing.from_string "\
five Nat 0 (fn n => n + 1)\n\
"
-
(*
let buf = Lexing.from_string "\
f := fn a: Nat, b: Nat, c: Nat, d: Nat, e: Nat, f: Nat, g: Nat, h: Nat =>\
@@ -43,7 +42,8 @@ let buf = Lexing.from_string "\
(*
let buf = Lexing.from_string "\
- (fn => Nat) ()\
+ `` := () : #();\
+ (fn => Nat) ``\
"
*)
@@ -89,11 +89,14 @@ let (internal, ty) = try
let abstract = Desugar.term concrete in
Elab.infer' ctx abstract
with Error.Exn e ->
- print Error.pp_print_error e;
+ print Error.pp_print e;
exit 1
let internal' = Quote.quote ctx.env (Eval.eval ctx.env internal)
let () =
print (Pretty.pp_print_term 0) internal;
+ print Format.pp_print_string "\
+ ----------------------------------------\
+ ----------------------------------------";
print (Pretty.pp_print_term 0) internal'
diff --git a/name.ml b/name.ml
@@ -1,3 +1,15 @@
+let non_start c = false
+ || ('0' <= c && c <= '9')
+ || c = '\''
+ || c = '"'
+
+let non_cont c = false
+ || c < '\''
+ || ('\'' < c && c < '0')
+ || ('9' < c && c < 'A')
+ || ('Z' < c && c < '_')
+ || ('z' < c && c < '\x7F')
+
module Var = struct
type var = Of of string
type t = var
@@ -11,8 +23,16 @@ module Var = struct
module Set = Set.Make(Ord)
- (* TODO: Doesn't handled backticked names. *)
- let pp_print ppf (Of s) = Format.fprintf ppf "%s" s
+ let requires_quotes (Of s) = false
+ || String.length s = 0
+ || non_start s.[0]
+ || String.exists non_cont s
+
+ let pp_print ppf (Of s as name) =
+ if requires_quotes name then
+ Format.fprintf ppf "`%s`" s
+ else
+ Format.fprintf ppf "%s" s
end
module Ctor = struct
@@ -28,7 +48,14 @@ module Ctor = struct
let equal (Of x) (Of y) = String.equal x y
- (* TODO: Doesn't handled backticked names. *)
- let pp_print ppf (Of s) = Format.fprintf ppf "%@%s" s
+ let requires_quotes (Of s) = false
+ || String.length s = 0
+ || String.exists non_cont s
+
+ let pp_print ppf (Of s as name) =
+ if requires_quotes name then
+ Format.fprintf ppf "%@`%s`" s
+ else
+ Format.fprintf ppf "%@%s" s
end
diff --git a/parser.mly b/parser.mly
@@ -1,7 +1,7 @@
%{
open Util
open Node
-open Error
+module E = Error
module C = Concrete
(* To avoid reduce-reduce conflicts, we need to distinguish between raw
@@ -56,8 +56,8 @@ let rec term {loc; data = e} = loc @$ match e with
| Iff (c, t) -> C.Iff (c, term t)
| Annot (a, b) -> C.Annot (term a, term b)
| BinOp (a, o, b) -> C.BinOp (term a, o, term b)
-| Or _ -> abort loc EParserInvalidTerm
-| And _ -> abort loc EParserInvalidTerm
+| Or _ -> E.abort loc E.ParserInvalidTerm
+| And _ -> E.abort loc E.ParserInvalidTerm
| App (f, len, args) -> C.App (term f, Array.map term (to_array len args))
| Fn (len, params, body) -> C.Fn (to_array len params, term body)
| FnType (len, doms, cod) -> C.FnType (to_array len doms, term cod)
@@ -67,7 +67,7 @@ let rec term {loc; data = e} = loc @$ match e with
| TupleType (len, doms) -> C.TupleType (to_array len doms)
| Unit -> C.Unit
| Nat n -> C.Nat n
-| Underscore -> abort loc EParserInvalidTerm
+| Underscore -> E.abort loc E.ParserInvalidTerm
| IndexedVar (x, i) -> C.IndexedVar (x, i)
| Var x -> C.Var x
| Paren e -> C.Paren (term e)
@@ -88,14 +88,14 @@ and patt {loc; data = e} = loc @$ match e with
| Paren p -> C.PParen (patt p)
| Let _ | Seq _ | Match _ | If _ | Iff _ | BinOp _ | App _
| Fn _ | FnType _ | VariantType _ | TupleType _ | IndexedVar _ ->
- abort loc EParserInvalidPatt
+ E.abort loc E.ParserInvalidPatt
let loc_of i =
let beg_pos = Parsing.rhs_start_pos i in
let end_pos = Parsing.rhs_end_pos i in
Loc.of_positions beg_pos end_pos
-let loc =
+let loc () =
let beg_pos = Parsing.symbol_start_pos () in
let end_pos = Parsing.symbol_end_pos () in
Loc.of_positions beg_pos end_pos
@@ -137,9 +137,9 @@ start: expr0 EOF { term $1 }
expr0: (* Definitions and sequencing *)
| definer_list SEMICOLON expr0 {
let (len, lst) = $1 in
- loc @$ Let (len, lst, $3)
+ loc () @$ Let (len, lst, $3)
}
- | expr1 SEMICOLON expr0 { loc @$ Seq ($1, $3) }
+ | expr1 SEMICOLON expr0 { loc () @$ Seq ($1, $3) }
| expr1 { $1 }
expr1: (* Control flow and functions *)
@@ -148,48 +148,48 @@ expr1: (* Control flow and functions *)
* `$(x match ...)` for conditional compilation. *)
| expr2 MATCH LBRACE case_list RBRACE {
let (len, lst) = $4 in
- loc @$ Match($1, len, lst)
+ loc () @$ Match($1, len, lst)
}
- | IF cond THEN expr1 ELSE expr1 { loc @$ If ($2, $4, $6) }
- | IFF cond DO expr1 { loc @$ Iff ($2, $4) }
+ | IF cond THEN expr1 ELSE expr1 { loc () @$ If ($2, $4, $6) }
+ | IFF cond DO expr1 { loc () @$ Iff ($2, $4) }
| FN param_list DOUBLE_ARROW expr1 {
let (len, lst) = $2 in
- loc @$ Fn (len, lst, $4)
+ loc () @$ Fn (len, lst, $4)
}
| expr2 { $1 }
expr2: (* Type annotations (right-associative) *)
- | expr3 COLON expr2 { loc @$ Annot ($1, $3) }
+ | expr3 COLON expr2 { loc () @$ Annot ($1, $3) }
| expr3 { $1 }
expr3: (* Function arrow (right-associative) *)
| expr6 SINGLE_ARROW expr3 {
let dom = loc_of 1 @$ C.ExplicitDomain (term $1) in
- loc @$ FnType (1, [dom], $3)
+ loc () @$ FnType (1, [dom], $3)
}
| LBRACK domain_list RBRACK SINGLE_ARROW expr3 {
let (len, lst) = $2 in
if len = 0 then
- abort (loc_of 2) EParserEmptyDomain
+ E.abort (loc_of 2) E.ParserEmptyDomain
else
- loc @$ FnType (len, lst, $5)
+ loc () @$ FnType (len, lst, $5)
}
| expr4 { $1 }
expr4: expr4a { $1 } (* Binary operators and relations *)
expr4a: (* Logical OR (left-associative) *)
- | expr4a PIPE2 expr4b { loc @$ BinOp ($1, C.LAnd, $3) }
+ | expr4a PIPE2 expr4b { loc () @$ BinOp ($1, C.LAnd, $3) }
| expr4b { $1 }
expr4b: (* Logical AND (left-associative) *)
- | expr4b AMPERSAND2 expr4c { loc @$ BinOp ($1, C.LOr, $3) }
+ | expr4b AMPERSAND2 expr4c { loc () @$ BinOp ($1, C.LOr, $3) }
| expr4c { $1 }
expr4c: (* Relations (non-associative) *)
(* TODO: Chaining relations? I.e., ability to write x < y < z instead of
* x < y && y < z. *)
- | expr4d rel expr4d { loc @$ BinOp ($1, $2, $3) }
+ | expr4d rel expr4d { loc () @$ BinOp ($1, $2, $3) }
| expr4d { $1 }
rel:
| LT { C.Lt }
@@ -200,32 +200,32 @@ rel:
| NE { C.Ne }
expr4d: (* Additive operators (left-associative) *)
- | expr4d0 addop expr4e { loc @$ BinOp ($1, $2, $3) }
- | expr4d1 PIPE expr4e { loc @$ Or ($1, $3) }
+ | expr4d0 addop expr4e { loc () @$ BinOp ($1, $2, $3) }
+ | expr4d1 PIPE expr4e { loc () @$ Or ($1, $3) }
| expr4e { $1 }
addop:
| PLUS { C.Add }
| MINUS { C.Sub }
expr4d0:
- | expr4d0 addop expr4e { loc @$ BinOp ($1, $2, $3) }
+ | expr4d0 addop expr4e { loc () @$ BinOp ($1, $2, $3) }
| expr4e { $1 }
expr4d1:
- | expr4d1 PIPE expr4e { loc @$ Or ($1, $3) }
+ | expr4d1 PIPE expr4e { loc () @$ Or ($1, $3) }
| expr4e { $1 }
expr4e: (* Multiplicative operators (left-associative) *)
- | expr4e0 mulop expr4f { loc @$ BinOp ($1, $2, $3) }
- | expr4e1 AMPERSAND expr4f { loc @$ And ($1, $3) }
+ | expr4e0 mulop expr4f { loc () @$ BinOp ($1, $2, $3) }
+ | expr4e1 AMPERSAND expr4f { loc () @$ And ($1, $3) }
| expr4f { $1 }
mulop:
| ASTERISK { C.Mul }
| SLASH { C.Div }
| PERCENT { C.Mod }
expr4e0:
- | expr4e0 mulop expr4f { loc @$ BinOp ($1, $2, $3) }
+ | expr4e0 mulop expr4f { loc () @$ BinOp ($1, $2, $3) }
| expr4f { $1 }
expr4e1:
- | expr4e1 AMPERSAND expr4f { loc @$ And ($1, $3) }
+ | expr4e1 AMPERSAND expr4f { loc () @$ And ($1, $3) }
| expr4f { $1 }
expr4f: expr5 { $1 }
@@ -233,36 +233,36 @@ expr4f: expr5 { $1 }
expr5:
| expr6 expr6 expr6_apposition_list {
let (len, lst) = $3 in
- loc @$ App ($1, len + 1, $2 :: lst)
+ loc () @$ App ($1, len + 1, $2 :: lst)
}
| ctor_name expr6_apposition_list {
let (len, lst) = $2 in
- loc @$ Variant ($1, len, lst)
+ loc () @$ Variant ($1, len, lst)
}
| expr6 { $1 }
expr6:
- | UNDERSCORE { loc @$ Underscore }
+ | UNDERSCORE { loc () @$ Underscore }
| indexed_var_name {
let (x, i) = $1 in
- loc @$ IndexedVar (x, i)
+ loc () @$ IndexedVar (x, i)
}
- | var_name { loc @$ Var $1 }
- | NAT { loc @$ Nat $1 }
+ | var_name { loc () @$ Var $1 }
+ | NAT { loc () @$ Nat $1 }
| HASH_LBRACE ctor_list RBRACE {
let (len, lst) = $2 in
- loc @$ VariantType (len, lst)
+ loc () @$ VariantType (len, lst)
}
| HASH_LPAREN domain_list RPAREN {
let (len, lst) = $2 in
- loc @$ TupleType (len, lst)
+ loc () @$ TupleType (len, lst)
}
| LPAREN expr1 COMMA expr1_comma_list RPAREN {
let (len, lst) = $4 in
- loc @$ Tuple (len + 1, $2 :: lst)
+ loc () @$ Tuple (len + 1, $2 :: lst)
}
- | LPAREN RPAREN { loc @$ Unit }
- | LPAREN expr0 RPAREN { loc @$ Paren $2 }
+ | LPAREN RPAREN { loc () @$ Unit }
+ | LPAREN expr0 RPAREN { loc () @$ Paren $2 }
expr1_comma_list:
| expr1 COMMA expr1_comma_list { cons $1 $3 }
@@ -274,57 +274,57 @@ expr6_apposition_list:
| { (0, []) }
definer:
- | expr2 COLON_EQ expr1 { loc @$ C.Definer (patt $1, term $3) }
- | expr2 COLON_EQ REC expr1 { loc @$ C.RecDefiner (patt $1, term $4) }
+ | expr2 COLON_EQ expr1 { loc () @$ C.Definer (patt $1, term $3) }
+ | expr2 COLON_EQ REC expr1 { loc () @$ C.RecDefiner (patt $1, term $4) }
definer_list:
| definer COMMA definer_list { cons $1 $3 }
| definer { (1, [$1]) }
case:
- | expr2 DOUBLE_ARROW expr1 { loc @$ C.Case (patt $1, term $3) }
+ | expr2 DOUBLE_ARROW expr1 { loc () @$ C.Case (patt $1, term $3) }
case_list:
| case COMMA case_list { cons $1 $3 }
| case { (1, [$1]) }
| { (0, []) }
cond:
- | expr1 { loc @$ C.TrueCond (term $1) }
- | expr2 COLON_EQ expr1 { loc @$ C.PattCond (patt $1, term $3) }
+ | expr1 { loc () @$ C.TrueCond (term $1) }
+ | expr2 COLON_EQ expr1 { loc () @$ C.PattCond (patt $1, term $3) }
param:
- | expr2 { loc @$ C.Param (Plicity.Ex, patt $1) }
- | QUESTION expr2 { loc @$ C.Param (Plicity.Im, patt $2) }
+ | expr2 { loc () @$ C.Param (Plicity.Ex, patt $1) }
+ | QUESTION expr2 { loc () @$ C.Param (Plicity.Im, patt $2) }
param_list:
| param COMMA param_list { cons $1 $3 }
| param { (1, [$1]) }
| { (0, []) }
domain:
- | expr3 { loc @$ C.ExplicitDomain (term $1) }
- | QUESTION expr3 { loc @$ C.ImplicitTypeDomain (patt $2) }
- | expr3 COLON expr2 { loc @$ C.AnnotDomain (Plicity.Ex, patt $1, term $3) }
- | QUESTION expr3 COLON expr2 { loc @$ C.AnnotDomain (Plicity.Im, patt $2, term $4) }
+ | expr3 { loc () @$ C.ExplicitDomain (term $1) }
+ | QUESTION expr3 { loc () @$ C.ImplicitTypeDomain (patt $2) }
+ | expr3 COLON expr2 { loc () @$ C.AnnotDomain (Plicity.Ex, patt $1, term $3) }
+ | QUESTION expr3 COLON expr2 { loc () @$ C.AnnotDomain (Plicity.Im, patt $2, term $4) }
domain_list:
| domain COMMA domain_list { cons $1 $3 }
| domain { (1, [$1]) }
| { (0, []) }
ctor_name:
- | TAG { loc @$ Name.Ctor.Of $1 }
+ | TAG { loc () @$ Name.Ctor.Of $1 }
indexed_var_name:
| INDEXED_NAME {
let (x, i) = $1 in
- (loc @$ Name.Var.Of x, i)
+ (loc () @$ Name.Var.Of x, i)
}
var_name:
- | NAME { loc @$ Name.Var.Of $1 }
+ | NAME { loc () @$ Name.Var.Of $1 }
ctor:
| ctor_name domain_list {
let (len, lst) = $2 in
- loc @$ Ctor ($1, len, lst)
+ loc () @$ Ctor ($1, len, lst)
}
ctor_list:
| ctor SEMICOLON ctor_list { cons $1 $3 }
diff --git a/pretty.ml b/pretty.ml
@@ -6,8 +6,8 @@ let rec pp_print_with_parens
: 'a. int -> int -> F.formatter -> ('a, F.formatter, unit) format -> 'a
= fun m c ppf ->
if c < m then begin
- F.fprintf ppf "(@[<h>";
- F.kfprintf (fun ppf -> F.fprintf ppf "@])") ppf
+ F.fprintf ppf "(";
+ F.kfprintf (fun ppf -> F.fprintf ppf ")") ppf
end else
F.fprintf ppf