Skip to content

Commit

Permalink
Implement hocc Hemlock/OCaml code generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Evans committed Aug 18, 2024
1 parent ca11ab4 commit 68f651c
Show file tree
Hide file tree
Showing 70 changed files with 12,854 additions and 1,283 deletions.
19 changes: 12 additions & 7 deletions bootstrap/bin/hocc/reduction.ml → bootstrap/bin/hocc/callback.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module T = struct
binding: string option;
symbol_name: string;
qtype: QualifiedType.t;
prod_param: Parse.prod_param option;
prod_param: Parse.nonterm_prod_param option;
}

let hash_fold {binding; symbol_name; _} state =
Expand Down Expand Up @@ -115,9 +115,10 @@ module T = struct
module Index = Uns
type t = {
index: Index.t;
lhs: QualifiedType.t;
lhs_name: string;
lhs_qtype: QualifiedType.t;
rhs: Params.t;
code: Parse.code option;
code: Parse.nonterm_code option;
}

let hash_fold {index; _} state =
Expand All @@ -126,16 +127,20 @@ module T = struct
let cmp {index=index0; _} {index=index1; _} =
Index.cmp index0 index1

let pp {index; lhs; rhs; code} formatter =
let pp {index; lhs_name; lhs_qtype; rhs; code} formatter =
formatter
|> Fmt.fmt "{index=" |> Index.pp index
|> Fmt.fmt "; lhs=" |> QualifiedType.pp lhs
|> Fmt.fmt "; lhs_name=" |> String.pp lhs_name
|> Fmt.fmt "; lhs_qtype=" |> QualifiedType.pp lhs_qtype
|> Fmt.fmt "; rhs=" |> Params.pp rhs
|> Fmt.fmt "; code=" |> (Option.pp Parse.fmt_code) code
|> Fmt.fmt "}"
end
include T
include Identifiable.Make(T)

let init ~index ~lhs ~rhs ~code =
{index; lhs; rhs; code}
let init ~index ~lhs_name ~lhs_qtype ~rhs ~code =
{index; lhs_name; lhs_qtype; rhs; code}

let is_epsilon {rhs; _} =
Params.is_empty rhs
72 changes: 72 additions & 0 deletions bootstrap/bin/hocc/callback.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
(** Reduction callback code associated with a production. Conceptually a reduction callback is
simply a block of code, but there is quite a bit of hair related to binding parameters to
production symbols. *)

open Basis
open Basis.Rudiments

(** Reduction callback parameter. *)
module Param : sig
type t = {
binding: string option;
(** Optional binding name for reduction callback code. Generated code must specify a binding for
each RHS symbol it needs to access. *)

symbol_name: string;
(** Symbol name corresponding to a [start]/[nonterm] or [token] declaration. *)

qtype: QualifiedType.t;
(** Qualified type of parameter, e.g. [explicit_opt=Some {module_:"SomeToken"; type_:"t"}]. *)

prod_param: Parse.nonterm_prod_param option;
(** Declaration AST. *)
}

include IdentifiableIntf.S with type t := t

val init: binding:string option -> symbol_name:string -> qtype:QualifiedType.t
-> prod_param:Parse.nonterm_prod_param option -> t
end

(** Ordered container of reduction callback parameters. *)
module Params : sig
type t
type elm = Param.t

include IdentifiableIntf.S with type t := t
include ContainerIntf.SMonoArray with type t := t with type elm := elm
include ContainerIntf.SMonoIndex with type t := t with type elm := elm

val init: Io.t -> Param.t array -> Io.t * t
val length: t -> uns
val range: t -> range
val get: uns -> t -> Param.t
val map: f:(Param.t -> 'a) -> t -> 'a array
end

module Index = Uns
type t = {
index: Index.t;
(** Unique reduction callback index. *)

lhs_name: string;
(** Name of enclosing nonterm. *)

lhs_qtype: QualifiedType.t;
(** Qualified type of LHS. *)

rhs: Params.t;
(** RHS parameters. *)

code: Parse.nonterm_code option;
(** Optional embedded code to be invoked by generated parser. *)
}

include IdentifiableIntf.S with type t := t

val init: index:Index.t -> lhs_name:string -> lhs_qtype:QualifiedType.t -> rhs:Params.t
-> code:Parse.nonterm_code option -> t
(** Used only by [Callbacks.init]. *)

val is_epsilon: t -> bool
(** [is_epsilon t] returns true if [t] is an ε reduction callback, i.e. it has an empty RHS. *)
16 changes: 16 additions & 0 deletions bootstrap/bin/hocc/callbacks.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
open Basis
open! Basis.Rudiments

type t = (Callback.Index.t, Callback.t, Callback.Index.cmper_witness) Ordmap.t

let empty = Ordmap.empty (module Callback.Index)

let length = Ordmap.length

let insert ~lhs:Symbols.{name; qtype; _} ~rhs ~code t =
let index = length t in
let callback = Callback.init ~index ~lhs_name:name ~lhs_qtype:qtype ~rhs ~code in
callback, Ordmap.insert_hlt ~k:index ~v:callback t

let fold ~init ~f t =
Ordmap.fold ~init ~f:(fun accum (_, callback) -> f accum callback) t
21 changes: 21 additions & 0 deletions bootstrap/bin/hocc/callbacks.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(** Collection of all reduction callbacks, with automatic assignment of unique indexes. *)
open! Basis
open! Basis.Rudiments

type t

val empty: t
(** [empty] returns an empty set of reduction callbacks. *)

val insert: lhs:Symbols.info -> rhs:Callback.Params.t -> code:Parse.nonterm_code option -> t
-> Callback.t * t
(** [insert ~lhs ~rhs ~code t] creates a [Callback.t] with unique index and returns both the
reduction callback and a new [t] with the reduction callback inserted. *)

val length: t -> uns
(** [length t] returns the number of reduction callbacks in [t]. *)

val fold: init:'accum -> f:('accum -> Callback.t -> 'accum) -> t -> 'accum
(** [fold ~init ~f t] iteratively applies [f] to the reduction callbacks in [t], in increasing index
order.
*)
Loading

0 comments on commit 68f651c

Please sign in to comment.