Skip to content

Commit

Permalink
Code generation for sets in various langauges
Browse files Browse the repository at this point in the history
Summary:
The only thing that's controversial here is that we encode sets as lists in OCaml. Generating code for sets in OCaml is a real pain because each form of element type requires a new instantiation of the `Set.Make` functor, i.e. a new module.
After discussing with mheiber we concluded that producing lists without duplicates is the most ergonomical for all parties.

Reviewed By: simonmar

Differential Revision: D63611594

fbshipit-source-id: 5bfab7402ac7c442be6fa55db07a42eb574f2360
  • Loading branch information
Josef Svenningsson authored and facebook-github-bot committed Oct 8, 2024
1 parent 004f254 commit e310725
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 6 deletions.
8 changes: 8 additions & 0 deletions glean/cpp/glean.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ struct Repr_<std::vector<T>> {
using Type = Array<Repr<T>>;
};

template <typename T>
struct Set;

template <typename T>
struct Repr_<std::set<T>> {
using Type = Set<Repr<T>>;
};

template <typename... Ts>
struct Tuple;
using Unit = Tuple<>;
Expand Down
2 changes: 1 addition & 1 deletion glean/db/Glean/Query/Incremental.hs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ expandGenerators hasFacts stmts =
Incremental (generator SeekOnStacked) (generator SeekOnBase)
CgStatement{} ->
Incremental Nothing (Just stmt)
CgAllStatement{} -> error "Set"
CgAllStatement{} -> Incremental Nothing (Just stmt)
CgDisjunction stmtss ->
CgDisjunction <$> expandDisjunction stmtss
CgNegation{} ->
Expand Down
8 changes: 6 additions & 2 deletions glean/schema/gen/Glean/Schema/Gen/Cpp.hs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ reprTy here t = case t of
SumTy fields -> do
ts <- mapM (reprTy here . fieldDefType) fields
return $ "Sum<" <> Text.intercalate ", " ts <> ">"
SetTy _ty -> error "Set"
SetTy ty -> do
rTy <- reprTy here ty
return $ "Set<" <> rTy <> ">"
MaybeTy ty -> do
rTy <- reprTy here ty
return $ "Maybe<" <> rTy <> ">"
Expand Down Expand Up @@ -324,7 +326,9 @@ valueTy here t = case t of
SumTy fields -> do
ts <- mapM (valueTy here .fieldDefType) fields
return $ "boost::variant<" <> Text.intercalate ", " (altsOf ts) <> ">"
SetTy _ty -> error "Set"
SetTy ty -> do
vTy <- valueTy here ty
return $ "std::set<" <> vTy <> ">"
MaybeTy ty ->
valueTy here $ SumTy
[ FieldDef "^Nothing^" unitT
Expand Down
3 changes: 2 additions & 1 deletion glean/schema/gen/Glean/Schema/Gen/HackJson.hs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ data AngleTypeRepr
| EnumeratedTEnum {alts::[Name], classname::Text}
| BooleanTBool
| ArrayTVec {inner::AngleTypeRepr}
| SetTSet {inner::AngleTypeRepr}
| RecordTShape {fields::[(Text, AngleTypeRepr)]}
| SumTShape {fields::[(Text, AngleTypeRepr)]}
| PredicateTKeyValue {pref::PredicateRef, classname::Text}
Expand Down Expand Up @@ -274,7 +275,7 @@ angleTypeInnerReprFor (SumTy fields) =
where
f FieldDef{..} =
(,) fieldDefName <$> angleTypeInnerReprFor fieldDefType
angleTypeInnerReprFor (SetTy _ty) = error "Set"
angleTypeInnerReprFor (SetTy ty) = SetTSet <$> angleTypeInnerReprFor ty
angleTypeInnerReprFor (PredicateTy ref) = do
ctx <- ask
case lookupPredDefKeyValue ctx ref of
Expand Down
1 change: 1 addition & 0 deletions glean/schema/gen/Glean/Schema/Gen/Haskell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ header here deps = Text.unlines $
, "import qualified Data.ByteString"
, "import qualified Data.Default"
, "import qualified Data.Text"
, "import qualified Data.Set"
, ""
-- we should use qualified imports as far as possible to avoid
-- clashing with Thrift-generated code
Expand Down
9 changes: 7 additions & 2 deletions glean/schema/gen/Glean/Schema/Gen/OCaml.hs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,9 @@ genOCamlType ns namePolicy t = case t of
SumTy fields -> do
f <- mapM (genField Sum) fields
return $ "\n" <> Text.intercalate "\n" f
SetTy _ty -> error "Set"
SetTy ty -> do
t <- genOCamlType ns namePolicy ty
return $ t <> " list" -- Suboptimal but sets in OCaml is such a pain
PredicateTy pred -> return $ predToModule ns pred namePolicy <> ".t"
NamedTy tref -> return $ typeToModule ns tref namePolicy <> ".t"
MaybeTy ty -> do
Expand Down Expand Up @@ -349,7 +351,10 @@ genOCamlToJson var ns namePolicy t = case t of
" -> JSON_Object [(\"", key, "\", ", genType, ")]"]
fields <- mapM typeSumField fields
return ("", "function\n" <> Text.unlines fields)
SetTy _ -> error "Set"
SetTy ty -> do
(_, code) <- genOCamlToJson "x" ns namePolicy ty
return (var, "JSON_Array (List.map ~f:(fun x -> " <> code <> ") "
<> var <> ")")
PredicateTy pred ->
let moduleName = predToModule ns pred namePolicy in
return (var, moduleName <> ".to_json " <> var)
Expand Down

0 comments on commit e310725

Please sign in to comment.