diff --git a/README.md b/README.md index 3be0f8eb..8cc6ad72 100644 --- a/README.md +++ b/README.md @@ -45,81 +45,24 @@ competitors if your project requires: ## Documentation -- [Design](./docs/design.md), -- [Compiler](./docs/compiler.md), -- [Codegen](./docs/codegen.md), -- [Comparison matrix](./docs/comparison-matrix.md), -- [User feedback](.docs/feedback) +Visit [LambdaBuffers Github Pages](https://mlabs-haskell.github.io/lambda-buffers). -## Getting started +## Acknowledgements -### Installing Nix +This project was graciously funded by the Cardano Treasury in [Catalyst Fund 9](https://cardano.ideascale.com/c/idea/421376). -This repository relies heavily on the [Nix Package -Manager](https://nixos.org/download.html) for both development and package -distribution. +Authors: -To install run the following command: +- [Drazen Popovic](https://github.com/bladyjoker) +- [Vlad Posmangiu Luchian](https://github.com/cstml) +- [Sean Hunter](https://github.com/gnumonik) -```sh -sh <(curl -L https://nixos.org/nix/install) --daemon -``` +Contributors: -and follow the instructions. - -```sh -$ nix --version -nix (Nix) 2.8.0 -``` - -> NOTE: The repository should work with Nix version greater or equal to 2.8.0. - -Make sure to enable [Nix Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes) -and IFD by editing either `~/.config/nix/nix.conf` or `/etc/nix/nix.conf` on -your machine and add the following configuration entries: - -```yaml -experimental-features = nix-command flakes -allow-import-from-derivation = true -``` - -Optionally, to improve build speed, it is possible to set up a binary caches -maintained by IOHK and Plutonomicon by setting additional configuration entries: - -```yaml -substituters = https://cache.nixos.org https://iohk.cachix.org https://cache.iog.io https://public-plutonomicon.cachix.org -trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= public-plutonomicon.cachix.org-1:3AKJMhCLn32gri1drGuaZmFrmnue+KkKrhhubQk/CWc= -``` - -### Building and development - -To facilitate seamlessly moving between directories and associated Nix -development shells we use [direnv](https://direnv.net) and -[nix-direnv](https://github.com/nix-community/nix-direnv): - -To install both using `nixpkgs`: - -```sh -nix profile install nixpkgs#direnv -nix profile install nixpkgs#nix-direnv -``` - -Your shell and editors should pick up on the `.envrc` files in different -directories and prepare the environment accordingly. Use `direnv allow` to -enable the direnv environment and `direnv reload` to reload it when necessary. - -Additionally, throughout the repository one can use: - -```sh -$ pre-commit run --all -cabal-fmt............................................(no files to check)Skipped -fourmolu.................................................................Passed -hlint....................................................................Passed -markdownlint.............................................................Passed -nix-linter...............................................................Passed -nixpkgs-fmt..............................................................Passed -shellcheck...........................................(no files to check)Skipped -typos....................................................................Passed -``` - -To run all the code quality tooling specified in the [pre-commit-check config file](./pre-commit.nix) +- [George Flerovsky](https://github.com/GeorgeFlerovsky) +- [Andrea Ciceri](https://github.com/aciceri) +- [Julia Chatain](https://juliachatain.com) +- [Andrea Vezzosi](https://github.com/saizan) +- [Magnus Viernickel](https://github.com/MangoIV) +- [Rajdeep Chase Maity](https://github.com/TotallyNotChase) +- [Ramiro Garay](https://github.com/rmgaray) diff --git a/lambda-buffers-proto/.envrc b/api/.envrc similarity index 100% rename from lambda-buffers-proto/.envrc rename to api/.envrc diff --git a/api/build.nix b/api/build.nix new file mode 100644 index 00000000..8d8e7ee6 --- /dev/null +++ b/api/build.nix @@ -0,0 +1,50 @@ +{ pkgs, pbnix-lib, commonTools, shellHook }: +rec { + devShell = pkgs.mkShell { + name = "protos-env"; + buildInputs = [ + pkgs.protobuf + pkgs.haskellPackages.proto-lens-protoc + pkgs.protoc-gen-doc + ] ++ builtins.attrValues commonTools; + + inherit shellHook; + }; + + packages = { + lambda-buffers-lang-hs-pb = pbnix-lib.haskellProto { + inherit pkgs; + src = ./.; + proto = "lang.proto"; + cabalPackageName = "lambda-buffers-lang-pb"; + }; + + lambda-buffers-compiler-hs-pb = pbnix-lib.haskellProto { + inherit pkgs; + src = ./.; + proto = "compiler.proto"; + cabalBuildDepends = [ packages.lambda-buffers-lang-hs-pb ]; + cabalPackageName = "lambda-buffers-compiler-pb"; + }; + + lambda-buffers-codegen-hs-pb = pbnix-lib.haskellProto { + inherit pkgs; + src = ./.; + proto = "codegen.proto"; + cabalBuildDepends = [ packages.lambda-buffers-lang-hs-pb ]; + cabalPackageName = "lambda-buffers-codegen-pb"; + }; + + lambda-buffers-api-docs = pkgs.stdenv.mkDerivation { + src = ./.; + name = "lambdabuffers-api-docs"; + buildInputs = [ + pkgs.protobuf + ]; + buildPhase = '' + mkdir $out; + protoc --plugin=${pkgs.protoc-gen-doc}/bin/protoc-gen-doc lang.proto compiler.proto codegen.proto --doc_out=$out --doc_opt=markdown,api.md; + ''; + }; + }; +} diff --git a/lambda-buffers-proto/codegen.proto b/api/codegen.proto similarity index 97% rename from lambda-buffers-proto/codegen.proto rename to api/codegen.proto index 3b07ef7f..3b2a8f48 100644 --- a/lambda-buffers-proto/codegen.proto +++ b/api/codegen.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package lambdabuffers; +package lambdabuffers.codegen; import "lang.proto"; diff --git a/lambda-buffers-proto/compiler.proto b/api/compiler.proto similarity index 99% rename from lambda-buffers-proto/compiler.proto rename to api/compiler.proto index da6ea1c9..65e79f17 100644 --- a/lambda-buffers-proto/compiler.proto +++ b/api/compiler.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package lambdabuffers; +package lambdabuffers.compiler; import "lang.proto"; diff --git a/lambda-buffers-proto/examples/tys.textproto b/api/examples/tys.textproto similarity index 100% rename from lambda-buffers-proto/examples/tys.textproto rename to api/examples/tys.textproto diff --git a/lambda-buffers-proto/lang.proto b/api/lang.proto similarity index 100% rename from lambda-buffers-proto/lang.proto rename to api/lang.proto diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index e782a39b..58a4b6ab 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,8 +1,12 @@ # Summary +- [Introduction](introduction.md) +- [Getting started](getting-started.md) +- [LambdaBuffers to Haskell](haskell.md) +- [LambdaBuffers to Purescript](purescript.md) - [Design](design.md) +- [API](api.md) - [Compiler](compiler.md) -- [Compiler API](compiler-api.md) - [Codegen](codegen.md) - [Command line interface](command-line-interface.md) - [Comparison matrix](comparison-matrix.md) diff --git a/docs/build.nix b/docs/build.nix index 678af849..8d073d99 100644 --- a/docs/build.nix +++ b/docs/build.nix @@ -1,8 +1,21 @@ -{ pkgs, commonTools, shellHook }: -pkgs.mkShell { - name = "docs-env"; +{ inputs, lib, ... }: { + perSystem = { pkgs, system, inputs', config, ... }: + { + devShells.dev-docs = pkgs.mkShell { + name = "docs-env"; + packages = [ pkgs.mdbook ]; + shellHook = config.pre-commit.installationScript; + }; - packages = [ commonTools.markdownlint-cli commonTools.typos pkgs.mdbook ]; + packages.lambda-buffers-book = pkgs.stdenv.mkDerivation { + src = ./.; + name = "lambda-buffers-book"; + buildInputs = [ pkgs.mdbook ]; + buildPhase = '' + cp ${config.packages.lambda-buffers-api-docs}/api.md api.md; + mdbook build . --dest-dir $out + ''; + }; - inherit shellHook; + }; } diff --git a/docs/compiler-api.md b/docs/compiler-api.md deleted file mode 100644 index 6b81a3c2..00000000 --- a/docs/compiler-api.md +++ /dev/null @@ -1,1460 +0,0 @@ -# Protocol Documentation - - -## Table of Contents - -- [compiler.proto](#compiler-proto) - - [ClassConstraint](#lambdabuffers-compiler-ClassConstraint) - - [ClassDef](#lambdabuffers-compiler-ClassDef) - - [ClassName](#lambdabuffers-compiler-ClassName) - - [CompilerError](#lambdabuffers-compiler-CompilerError) - - [CompilerInput](#lambdabuffers-compiler-CompilerInput) - - [CompilerOutput](#lambdabuffers-compiler-CompilerOutput) - - [CompilerResult](#lambdabuffers-compiler-CompilerResult) - - [ConstrName](#lambdabuffers-compiler-ConstrName) - - [Constraint](#lambdabuffers-compiler-Constraint) - - [Derive](#lambdabuffers-compiler-Derive) - - [FieldName](#lambdabuffers-compiler-FieldName) - - [InstanceClause](#lambdabuffers-compiler-InstanceClause) - - [InternalError](#lambdabuffers-compiler-InternalError) - - [Kind](#lambdabuffers-compiler-Kind) - - [Kind.KindArrow](#lambdabuffers-compiler-Kind-KindArrow) - - [KindCheckError](#lambdabuffers-compiler-KindCheckError) - - [KindCheckError.CyclicKindError](#lambdabuffers-compiler-KindCheckError-CyclicKindError) - - [KindCheckError.InconsistentTypeError](#lambdabuffers-compiler-KindCheckError-InconsistentTypeError) - - [KindCheckError.UnboundTyRefError](#lambdabuffers-compiler-KindCheckError-UnboundTyRefError) - - [KindCheckError.UnboundTyVarError](#lambdabuffers-compiler-KindCheckError-UnboundTyVarError) - - [KindCheckError.UnificationError](#lambdabuffers-compiler-KindCheckError-UnificationError) - - [Module](#lambdabuffers-compiler-Module) - - [ModuleName](#lambdabuffers-compiler-ModuleName) - - [ModuleNamePart](#lambdabuffers-compiler-ModuleNamePart) - - [NamingError](#lambdabuffers-compiler-NamingError) - - [Opaque](#lambdabuffers-compiler-Opaque) - - [Product](#lambdabuffers-compiler-Product) - - [ProtoParseError](#lambdabuffers-compiler-ProtoParseError) - - [ProtoParseError.MultipleClassDefError](#lambdabuffers-compiler-ProtoParseError-MultipleClassDefError) - - [ProtoParseError.MultipleConstructorError](#lambdabuffers-compiler-ProtoParseError-MultipleConstructorError) - - [ProtoParseError.MultipleFieldError](#lambdabuffers-compiler-ProtoParseError-MultipleFieldError) - - [ProtoParseError.MultipleImportError](#lambdabuffers-compiler-ProtoParseError-MultipleImportError) - - [ProtoParseError.MultipleModuleError](#lambdabuffers-compiler-ProtoParseError-MultipleModuleError) - - [ProtoParseError.MultipleTyArgError](#lambdabuffers-compiler-ProtoParseError-MultipleTyArgError) - - [ProtoParseError.MultipleTyDefError](#lambdabuffers-compiler-ProtoParseError-MultipleTyDefError) - - [ProtoParseError.OneOfNotSetError](#lambdabuffers-compiler-ProtoParseError-OneOfNotSetError) - - [ProtoParseError.UnknownEnumError](#lambdabuffers-compiler-ProtoParseError-UnknownEnumError) - - [Record](#lambdabuffers-compiler-Record) - - [Record.Field](#lambdabuffers-compiler-Record-Field) - - [SourceInfo](#lambdabuffers-compiler-SourceInfo) - - [SourcePosition](#lambdabuffers-compiler-SourcePosition) - - [Sum](#lambdabuffers-compiler-Sum) - - [Sum.Constructor](#lambdabuffers-compiler-Sum-Constructor) - - [Ty](#lambdabuffers-compiler-Ty) - - [TyAbs](#lambdabuffers-compiler-TyAbs) - - [TyApp](#lambdabuffers-compiler-TyApp) - - [TyArg](#lambdabuffers-compiler-TyArg) - - [TyBody](#lambdabuffers-compiler-TyBody) - - [TyClassCheckError](#lambdabuffers-compiler-TyClassCheckError) - - [TyClassCheckError.DeriveOpaqueError](#lambdabuffers-compiler-TyClassCheckError-DeriveOpaqueError) - - [TyClassCheckError.ImportNotFoundError](#lambdabuffers-compiler-TyClassCheckError-ImportNotFoundError) - - [TyClassCheckError.MissingRuleError](#lambdabuffers-compiler-TyClassCheckError-MissingRuleError) - - [TyClassCheckError.OverlappingRulesError](#lambdabuffers-compiler-TyClassCheckError-OverlappingRulesError) - - [TyClassCheckError.OverlappingRulesError.QHead](#lambdabuffers-compiler-TyClassCheckError-OverlappingRulesError-QHead) - - [TyClassCheckError.SuperclassCycleError](#lambdabuffers-compiler-TyClassCheckError-SuperclassCycleError) - - [TyClassCheckError.UnboundClassRefError](#lambdabuffers-compiler-TyClassCheckError-UnboundClassRefError) - - [TyClassRef](#lambdabuffers-compiler-TyClassRef) - - [TyClassRef.Foreign](#lambdabuffers-compiler-TyClassRef-Foreign) - - [TyClassRef.Local](#lambdabuffers-compiler-TyClassRef-Local) - - [TyDef](#lambdabuffers-compiler-TyDef) - - [TyName](#lambdabuffers-compiler-TyName) - - [TyRef](#lambdabuffers-compiler-TyRef) - - [TyRef.Foreign](#lambdabuffers-compiler-TyRef-Foreign) - - [TyRef.Local](#lambdabuffers-compiler-TyRef-Local) - - [TyVar](#lambdabuffers-compiler-TyVar) - - [Tys](#lambdabuffers-compiler-Tys) - - [VarName](#lambdabuffers-compiler-VarName) - - - [Kind.KindRef](#lambdabuffers-compiler-Kind-KindRef) - -- [Scalar Value Types](#scalar-value-types) - - - - -

Top

- -## compiler.proto - - - - - -### ClassConstraint -Class constraints - -A special constraint type denoting the constraints that occur on the rhs of -class definitions. Only used to specify super class constraints in a -`ClassDef`. - -Not to be confused with `Constraint` which denote type class rules. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| class_ref | [TyClassRef](#lambdabuffers-compiler-TyClassRef) | | Type class reference. | -| args | [TyVar](#lambdabuffers-compiler-TyVar) | repeated | Type variables quantified over `ClassDef` arguments. | - - - - - - - - -### ClassDef -Type class definition - -LambdaBuffers use type classes to talk about the various 'meanings' or -'semantics' we want to associate with the types in LambdaBuffers schemata. - -For instance, most types can have `Eq` semantics, meaning they can be -compared for equality. Other can have `Ord` semantics, meaning they can be -ordered. - -Using type classes and instance declarations, much like in Haskell, users can -specify the 'meaning' of each type they declare. For example, serialization -in LambdaBuffers is just another type class, it's treated the same as any -other type class. Concretely, if we wish to provide JSON serialization for -LambdaBuffers types, we declare such a type class and provide desired -semantic rules: - -```lbf -module Foo - -class JSON a - -sum Foo a b = Bar a | Baz b - -derive JSON (Foo a b) -``` - -Note that for each type class introduced, the Codegen machinery must be -updated to support said type class. In other words, it doesn't come for free -and for each new type class, a Codegen support must be implemented for any -`InstanceClause` declared by the user. Once all the `InstanceClause`s have an -implementation provided, all the `Derive`d implementation come for free. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| class_name | [ClassName](#lambdabuffers-compiler-ClassName) | | Type class name. | -| class_args | [TyArg](#lambdabuffers-compiler-TyArg) | repeated | Type class arguments. Class with no arguments is a trivial class. Compiler MAY report an error. TODO(bladyjoker): MultipleClassArgError. | -| supers | [ClassConstraint](#lambdabuffers-compiler-ClassConstraint) | repeated | Superclass constraints. | -| documentation | [string](#string) | | Documentation elaborating on the type class. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### ClassName -Type class name - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | | Name ::= [A-Z]+[A-Za-z0-9_]* | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### CompilerError -Compiler Error - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| proto_parse_errors | [ProtoParseError](#lambdabuffers-compiler-ProtoParseError) | repeated | Errors occurred during proto parsing. | -| naming_errors | [NamingError](#lambdabuffers-compiler-NamingError) | repeated | Errors occurred during naming checking. | -| kind_check_errors | [KindCheckError](#lambdabuffers-compiler-KindCheckError) | repeated | Errors occurred during kind checking. | -| ty_class_check_errors | [TyClassCheckError](#lambdabuffers-compiler-TyClassCheckError) | repeated | Errors occurred during type class checking. | -| internal_errors | [InternalError](#lambdabuffers-compiler-InternalError) | repeated | Errors internal to the compiler implementation. | - - - - - - - - -### CompilerInput -Compiler Input - -Compiler Input is a fully self contained list of modules, the entire -compilation closure needed by the Compiler to perform its task. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| modules | [Module](#lambdabuffers-compiler-Module) | repeated | Modules to compile. Duplicate modules MUST be reported with `ProtoParseError.MultipleModuleError`. | - - - - - - - - -### CompilerOutput -Output of the Compiler. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| compiler_error | [CompilerError](#lambdabuffers-compiler-CompilerError) | | | -| compiler_result | [CompilerResult](#lambdabuffers-compiler-CompilerResult) | | | - - - - - - - - -### CompilerResult -Compiler Result ~ a successful Compilation Output. - - - - - - - - -### ConstrName -Sum type constructor name - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | | Name ::= [A-Z]+[A-Za-z0-9_]* | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### Constraint -Constraint term - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| class_ref | [TyClassRef](#lambdabuffers-compiler-TyClassRef) | | Name of the type class. | -| args | [Ty](#lambdabuffers-compiler-Ty) | repeated | Constraint arguments. Constraint with no arguments is a trivial constraint. Compiler MAY report an error. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### Derive -Derive statement - -Derive statements enable user to specify 'semantic' rules for their types much -like `InstanceClause`s do. However, the Codegen will be able to derive an -implementation for any such constraint. - -```lbf -module Prelude - -class Eq a - -sum Maybe a = Just a | Nothing - -derive Eq (Maybe a) -``` - -The rule installed for the derive statement is: - -```prolog -eq(maybe(A)) :- eq(just(A) | Nothing). -``` - -The rule relates the desired `Ty` term to its (lambda calculus) -'evaluated' form. - -> Currently, there's only support for deriving type class rules and -implementations for `Ty` terms of `Kind.KIND_REF_TYPE`. That means, -type classes like Ord and Eq... - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | Constraint to derive. | - - - - - - - - -### FieldName -Record type field name - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | | Name ::= [a-z]+[A-Za-z0-9_]* | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### InstanceClause -Instance clause - -Instance clauses enable users to specify ad-hoc 'semantic' rules for their -types. Each such instance must be supported explicitly in the Codegen by -providing runtime implementations. - -This rule form is used when declaring 'opaque' implementations on `Opaque` -types. - -```lbf -module Prelude - -class Eq a - -opaque Maybe a - -instance Eq a => Eq (Maybe a) -``` - -The rule installed for the clause is: - -```prolog -eq(maybe(A)) :- eq(A). -``` - -The instance clause is verbatim added to the rule set. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| head | [Constraint](#lambdabuffers-compiler-Constraint) | | Head of the clause that holds only when the `body` holds. Type variables introduced in the head of the rule become available in the scope of the body of the rule. | -| constraints | [Constraint](#lambdabuffers-compiler-Constraint) | repeated | Instance (rule) body, conjunction of constraints. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### InternalError -Errors internal to the implementation. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| msg | [string](#string) | | Error message. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information if meaningful. | - - - - - - - - -### Kind -Kinds - -A type of a type is called a 'kind'. -In Lambda Buffers, all type terms, namely TyArg, TyVar, TyRef, TyApp and TyAbs, -are either of kind `Type` or `Type -> Type` and `Type -> Type -> Type` -etc. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| kind_ref | [Kind.KindRef](#lambdabuffers-compiler-Kind-KindRef) | | | -| kind_arrow | [Kind.KindArrow](#lambdabuffers-compiler-Kind-KindArrow) | | | - - - - - - - - -### Kind.KindArrow -A kind arrow. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| left | [Kind](#lambdabuffers-compiler-Kind) | | | -| right | [Kind](#lambdabuffers-compiler-Kind) | | | - - - - - - - - -### KindCheckError -Kind checking errors. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| unbound_ty_ref_error | [KindCheckError.UnboundTyRefError](#lambdabuffers-compiler-KindCheckError-UnboundTyRefError) | | | -| unbound_ty_var_error | [KindCheckError.UnboundTyVarError](#lambdabuffers-compiler-KindCheckError-UnboundTyVarError) | | | -| unification_error | [KindCheckError.UnificationError](#lambdabuffers-compiler-KindCheckError-UnificationError) | | | -| cyclic_kind_error | [KindCheckError.CyclicKindError](#lambdabuffers-compiler-KindCheckError-CyclicKindError) | | | -| inconsistent_type_error | [KindCheckError.InconsistentTypeError](#lambdabuffers-compiler-KindCheckError-InconsistentTypeError) | | | - - - - - - - - -### KindCheckError.CyclicKindError -A cyclic kind was encountered. Infinite kinds like this are not acceptable, -and we do not support them. We could not construct infinite kind in ty_def. - -As the implementation currently stands such an error is (most likely) not -representable - therefore not reachable. Such an error would usually occur -for a term like: λa. a a - in which case the inference would try to unify -two kinds of the form: m and m -> n - because m appears in both terms - -the cyclic unification error would be thrown. - -In the case of LambdaBuffers - such an error is not (currently) achievable -as the kind of the variable is given by the context - (i.e. λa : m . a a, -where m is a kind) therefore the unification would fail with Unification -Error. Nevertheless - future features might require it. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | - - - - - - - - -### KindCheckError.InconsistentTypeError -The actual_kind differs from the expected_kind. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | | -| actual_kind | [Kind](#lambdabuffers-compiler-Kind) | | | -| expected_kind | [Kind](#lambdabuffers-compiler-Kind) | | | - - - - - - - - -### KindCheckError.UnboundTyRefError -Unbound type reference ty_ref detected in term ty_def. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | | -| ty_ref | [TyRef](#lambdabuffers-compiler-TyRef) | | | - - - - - - - - -### KindCheckError.UnboundTyVarError -Unbound variable ty_var detected in term ty_def. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | | -| ty_var | [TyVar](#lambdabuffers-compiler-TyVar) | | | - - - - - - - - -### KindCheckError.UnificationError -In ty_def an error has occurred when trying to unify kind ty_kind_lhs -with ty_kind_rhs. - -FIXME(cstml): Add source of constraint to the error such that user can see -where the constraint was generated - therefore where the error precisely -is. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | | -| ty_kind_lhs | [Kind](#lambdabuffers-compiler-Kind) | | | -| ty_kind_rhs | [Kind](#lambdabuffers-compiler-Kind) | | | - - - - - - - - -### Module -Module - -A module encapsulates type, class and instance definitions. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module name. | -| type_defs | [TyDef](#lambdabuffers-compiler-TyDef) | repeated | Type definitions. Duplicate type definitions MUST be reported with `ProtoParseError.MultipleTyDefError`. | -| class_defs | [ClassDef](#lambdabuffers-compiler-ClassDef) | repeated | Type class definitions. Duplicate class definitions MUST be reported with `ProtoParseError.MultipleClassDefError`. | -| instances | [InstanceClause](#lambdabuffers-compiler-InstanceClause) | repeated | Type class instance clauses. | -| derives | [Derive](#lambdabuffers-compiler-Derive) | repeated | Type class derive statements. | -| imports | [ModuleName](#lambdabuffers-compiler-ModuleName) | repeated | Imported modules the Compiler consults when searching for type class rules. TODO(bladyjoker): Rename to ruleImports. Duplicate imports MUST be reported with `ProtoParseError.MultipleImportError`. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### ModuleName -Module name - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| parts | [ModuleNamePart](#lambdabuffers-compiler-ModuleNamePart) | repeated | Parts of the module name denoting a hierarchichal namespace. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### ModuleNamePart -Module name part - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | | Name ::= [A-Z]+[A-Za-z0-9_]* | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### NamingError -Naming error message - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name_err | [ModuleNamePart](#lambdabuffers-compiler-ModuleNamePart) | | | -| ty_name_err | [TyName](#lambdabuffers-compiler-TyName) | | | -| var_name_err | [VarName](#lambdabuffers-compiler-VarName) | | | -| constr_name_err | [ConstrName](#lambdabuffers-compiler-ConstrName) | | | -| field_name_err | [FieldName](#lambdabuffers-compiler-FieldName) | | | -| class_name_err | [ClassName](#lambdabuffers-compiler-ClassName) | | | - - - - - - - - -### Opaque -Opaque type. - -A type that has an `Opaque` body represents a 'built-in' or a 'primitive' type -that's handled by the semantics 'under the hood'. It's called 'opaque' to denote -the fact that the Compiler has no knowledge of its structure, and relies that -the necessary knowledge is implemented elsewhere. The Codegen modules for any -target language have to be able to handle such types specifically and map to -existing value level representations and corresponding types. - -Codegen modules would have to implement support for such defined types, for -example: -- In Python `Set a` would map to `set()` from the standard library, -- In Haskell `Set a` would map to `containers`.Data.Set.Set type. - -Every `Opaque` type has to be considered deliberately for each language -environment targeted by Codegen modules. - -TODO(bladyjoker): Consider attaching explicit Kind terms to Opaques. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### Product -A product type term. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| fields | [Ty](#lambdabuffers-compiler-Ty) | repeated | Fields in a products are types. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### ProtoParseError -All errors that occur because of Google Protocol Buffer's inability to -enforce certain invariants. -Some of invariance: -- using Proto `map` restricts users to `string` keys which impacts - API documentation, which is why `repeated` fields are used throughout, -- using Proto 'oneof' means users have to check if such a field is - set or report an error otherwise. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| multiple_module_error | [ProtoParseError.MultipleModuleError](#lambdabuffers-compiler-ProtoParseError-MultipleModuleError) | | | -| multiple_tydef_error | [ProtoParseError.MultipleTyDefError](#lambdabuffers-compiler-ProtoParseError-MultipleTyDefError) | | | -| multiple_classdef_error | [ProtoParseError.MultipleClassDefError](#lambdabuffers-compiler-ProtoParseError-MultipleClassDefError) | | | -| multiple_tyarg_error | [ProtoParseError.MultipleTyArgError](#lambdabuffers-compiler-ProtoParseError-MultipleTyArgError) | | | -| multiple_constructor_error | [ProtoParseError.MultipleConstructorError](#lambdabuffers-compiler-ProtoParseError-MultipleConstructorError) | | | -| multiple_field_error | [ProtoParseError.MultipleFieldError](#lambdabuffers-compiler-ProtoParseError-MultipleFieldError) | | | -| multiple_import_error | [ProtoParseError.MultipleImportError](#lambdabuffers-compiler-ProtoParseError-MultipleImportError) | | | -| one_of_not_set_error | [ProtoParseError.OneOfNotSetError](#lambdabuffers-compiler-ProtoParseError-OneOfNotSetError) | | | -| unknown_enum_error | [ProtoParseError.UnknownEnumError](#lambdabuffers-compiler-ProtoParseError-UnknownEnumError) | | | - - - - - - - - -### ProtoParseError.MultipleClassDefError -Multiple ClassDefs with the same ClassName were found in ModuleName. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module in which the error was found. | -| class_defs | [ClassDef](#lambdabuffers-compiler-ClassDef) | repeated | Conflicting class definitions. | - - - - - - - - -### ProtoParseError.MultipleConstructorError -Multiple Sum Constructors with the same ConstrName were found in -ModuleName.TyDef. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module in which the error was found. | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | Type definition in which the error was found. | -| constructors | [Sum.Constructor](#lambdabuffers-compiler-Sum-Constructor) | repeated | Conflicting constructors. | - - - - - - - - -### ProtoParseError.MultipleFieldError -Multiple Record Fields with the same FieldName were found in -ModuleName.TyDef. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module in which the error was found. | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | Type definition in which the error was found. | -| fields | [Record.Field](#lambdabuffers-compiler-Record-Field) | repeated | Conflicting record fields. | - - - - - - - - -### ProtoParseError.MultipleImportError - - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module in which the error was found. | -| imports | [ModuleName](#lambdabuffers-compiler-ModuleName) | repeated | Conflicting module imports. | - - - - - - - - -### ProtoParseError.MultipleModuleError -Multiple Modules with the same ModuleName were found. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| modules | [Module](#lambdabuffers-compiler-Module) | repeated | Conflicting type definitions. | - - - - - - - - -### ProtoParseError.MultipleTyArgError -Multiple TyArgs with the same ArgName were found in ModuleName.TyDef. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module in which the error was found. | -| ty_def | [TyDef](#lambdabuffers-compiler-TyDef) | | Type definition in which the error was found. | -| ty_args | [TyArg](#lambdabuffers-compiler-TyArg) | repeated | Conflicting type abstraction arguments. | - - - - - - - - -### ProtoParseError.MultipleTyDefError -Multiple TyDefs with the same TyName were found in ModuleName. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Module in which the error was found. | -| ty_defs | [TyDef](#lambdabuffers-compiler-TyDef) | repeated | Conflicting type definitions. | - - - - - - - - -### ProtoParseError.OneOfNotSetError -Proto `oneof` field is not set. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| message_name | [string](#string) | | Proto message name in which the `oneof` field is not set. | -| field_name | [string](#string) | | The `oneof` field that is not set. | - - - - - - - - -### ProtoParseError.UnknownEnumError -Proto `enum` field is unknown. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| enum_name | [string](#string) | | Proto `enum` name. | -| got_tag | [string](#string) | | The unknown tag for the `enum`. | - - - - - - - - -### Record -A record type term. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| fields | [Record.Field](#lambdabuffers-compiler-Record-Field) | repeated | Record fields. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### Record.Field -Field in a record type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| field_name | [FieldName](#lambdabuffers-compiler-FieldName) | | Record field name. | -| field_ty | [Ty](#lambdabuffers-compiler-Ty) | | Field type. | - - - - - - - - -### SourceInfo -Frontend Source information - -Frontends are advised to include *Source* information to denote how their -Source* content maps to the *Compiler Input*. It's essential when reporting -Compiler* errors back to the Frontend. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| file | [string](#string) | | A filename denoting the Source file. | -| pos_from | [SourcePosition](#lambdabuffers-compiler-SourcePosition) | | Starting position in Source. | -| pos_to | [SourcePosition](#lambdabuffers-compiler-SourcePosition) | | End position in Source. | - - - - - - - - -### SourcePosition -Position in Source - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| column | [int32](#int32) | | Column index in the Source. | -| row | [int32](#int32) | | Row index in the Source. | - - - - - - - - -### Sum -A sum type term. - -A type defined as a Sum type is just like a Haskell algebraic data type and -represents a sum of products. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| constructors | [Sum.Constructor](#lambdabuffers-compiler-Sum-Constructor) | repeated | Sum type constructors. Empty `constructors` means `void` and means that the type can't be constructed. Compiler MAY report an error. Duplicate constructors MUST be reported with `ProtoParseError.MultipleConstructorError`. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### Sum.Constructor -Constructor of a Sum type is a Product type term. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| constr_name | [ConstrName](#lambdabuffers-compiler-ConstrName) | | Constructor name. | -| product | [Product](#lambdabuffers-compiler-Product) | | Product type term. | - - - - - - - - -### Ty -Type term - -A type term that ocurrs in bodies of type definitions (message TyDef): - -```lbf -sum Maybe a = Just a | Nothing - -sum Either a b = Left a | Right b - -sum SomeType a = Foo a (Maybe a) | Bar (Either (Maybe a) (SomeType a)) -``` - -or in instance declarations: - -```lbf -instance Eq (Maybe a) - -instance Eq (SomeType Int) - -instance (Eq (Maybe a), Eq (SomeType a)) Eq (Either (Maybe a) (SomeType a)) -``` - -Check out [examples](examples/tys.textproto). - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_var | [TyVar](#lambdabuffers-compiler-TyVar) | | A type variable. | -| ty_app | [TyApp](#lambdabuffers-compiler-TyApp) | | A type application. | -| ty_ref | [TyRef](#lambdabuffers-compiler-TyRef) | | A type reference. | - - - - - - - - -### TyAbs -Type abstraction - -A type term that introduces type abstractions (ie. type functions). This -type term can only be introduced in the context of a -[type definition](@ref TyDef). - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_args | [TyArg](#lambdabuffers-compiler-TyArg) | repeated | List of type variables. No type arguments means `delay` or `const ty_body`, meaning `TyAbs [] ty_body = ty_body`. Duplicate type arguments MUST be reported with `ProtoParseError.MultipleTyArgError`. | -| ty_body | [TyBody](#lambdabuffers-compiler-TyBody) | | Type body. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyApp -Type application - -A type term that applies a type abstraction to a list of arguments. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_func | [Ty](#lambdabuffers-compiler-Ty) | | Type function. TODO(bladyjoker): Rename to ty_abs? | -| ty_args | [Ty](#lambdabuffers-compiler-Ty) | repeated | Arguments to apply. No arguments to apply means `force`, meaning `TyApp ty_func [] = ty_func`` | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyArg -Type arguments - -Arguments in type abstractions. - -Type arguments and therefore type variables have kinds, the Compiler only -accepts `Type` kinded type arguments ans therefore type variables. - -However, to allow for future evolution if ever necessary, we attach the Kind -term to type arguments, even though the Compiler will reject any TyArg that's -not of kind `Type`. - -Note, this effectively means that lambda Buffers doesn't support higher-kinded -types (ie. HKT). - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| arg_name | [VarName](#lambdabuffers-compiler-VarName) | | Argument name corresponds to variable names. | -| arg_kind | [Kind](#lambdabuffers-compiler-Kind) | | Argument kind. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyBody -Type body. - -Lambda Buffers type bodies type terms that can only be specified in the -`TyAbs` context. It's a built-in type term that can only occur enclosed -within a `TyAbs` term which introduces `TyVar`s in the scope of the term. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| opaque | [Opaque](#lambdabuffers-compiler-Opaque) | | | -| sum | [Sum](#lambdabuffers-compiler-Sum) | | | -| product | [Product](#lambdabuffers-compiler-Product) | | | -| record | [Record](#lambdabuffers-compiler-Record) | | | - - - - - - - - -### TyClassCheckError -Type class checking errors. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| unbound_class_ref_err | [TyClassCheckError.UnboundClassRefError](#lambdabuffers-compiler-TyClassCheckError-UnboundClassRefError) | | | -| superclass_cycle_err | [TyClassCheckError.SuperclassCycleError](#lambdabuffers-compiler-TyClassCheckError-SuperclassCycleError) | | | -| import_not_found_err | [TyClassCheckError.ImportNotFoundError](#lambdabuffers-compiler-TyClassCheckError-ImportNotFoundError) | | | -| derive_opaque_err | [TyClassCheckError.DeriveOpaqueError](#lambdabuffers-compiler-TyClassCheckError-DeriveOpaqueError) | | | -| missing_rule_err | [TyClassCheckError.MissingRuleError](#lambdabuffers-compiler-TyClassCheckError-MissingRuleError) | | | -| overlapping_rules_err | [TyClassCheckError.OverlappingRulesError](#lambdabuffers-compiler-TyClassCheckError-OverlappingRulesError) | | | - - - - - - - - -### TyClassCheckError.DeriveOpaqueError -In `module_name` it wasn't possible to solve `constraint` because a -`sub_constraint` has been derived on an `Opaque` type. `Opaque` type can -only have an `InstanceClause` declared for them. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | | -| sub_constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | | - - - - - - - - -### TyClassCheckError.ImportNotFoundError -Import `missing` wasn't found in `module_name` - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| missing | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | - - - - - - - - -### TyClassCheckError.MissingRuleError -In `module_name` while trying to solve `constraint` it wasn't possible to -find a rule (`Derive` or `InstanceClause`) for `sub_constraint`. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | | -| sub_constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | | - - - - - - - - -### TyClassCheckError.OverlappingRulesError -In `module_name` while trying to solve `constraint` `overlaps` (`Derive` -or `InstanceClause`) were found that could be used to solve the -`sub_constraint`. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | | -| sub_constraint | [Constraint](#lambdabuffers-compiler-Constraint) | | | -| overlaps | [TyClassCheckError.OverlappingRulesError.QHead](#lambdabuffers-compiler-TyClassCheckError-OverlappingRulesError-QHead) | repeated | | - - - - - - - - -### TyClassCheckError.OverlappingRulesError.QHead -NOTE(bladyjoker): This should rather be oneof `Derive` and -`InstanceClause`. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| head | [Constraint](#lambdabuffers-compiler-Constraint) | | | - - - - - - - - -### TyClassCheckError.SuperclassCycleError -Superclass cycle `cycled_class_refs` was detected when checking a -class definition for `class_name` in module `module_name`. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| class_name | [ClassName](#lambdabuffers-compiler-ClassName) | | | -| cycled_class_refs | [TyClassRef](#lambdabuffers-compiler-TyClassRef) | repeated | | - - - - - - - - -### TyClassCheckError.UnboundClassRefError -Unbound `class_ref` detected in `module_name`. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | | -| class_ref | [TyClassRef](#lambdabuffers-compiler-TyClassRef) | | | - - - - - - - - -### TyClassRef -Type class references - -It is necessary to know whether a type class is defined locally or in a -foreign module when referring to it in a constraint, this allows users (and -requires the frontend) to explicitly communicate that information. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| local_class_ref | [TyClassRef.Local](#lambdabuffers-compiler-TyClassRef-Local) | | | -| foreign_class_ref | [TyClassRef.Foreign](#lambdabuffers-compiler-TyClassRef-Foreign) | | | - - - - - - - - -### TyClassRef.Foreign -Foreign class reference. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| class_name | [ClassName](#lambdabuffers-compiler-ClassName) | | Foreign module class name. | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Foreign module name. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyClassRef.Local -Local type reference. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| class_name | [ClassName](#lambdabuffers-compiler-ClassName) | | Local module class name. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyDef -Type definition - -A type definition consists of a type name and its associated type term. - -One way to look at it is that a type definition introduces a named 'type -abstraction' in the module scope. Concretely, `Either` can be considered a type -lambda of kind `Type -> Type -> Type`. - -In fact, type definitions are the only way to introduce such types. - -Once introduced in the module scope, type definitions are referred to using -[TyRef](@ref TyRef) term. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_name | [TyName](#lambdabuffers-compiler-TyName) | | Type name. | -| ty_abs | [TyAbs](#lambdabuffers-compiler-TyAbs) | | Type term. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyName -Type name - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | | Name ::= [A-Z]+[A-Za-z0-9_]* | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyRef -Type reference - -A type term that denotes a reference to a type available that's declared -locally or in foreign modules. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| local_ty_ref | [TyRef.Local](#lambdabuffers-compiler-TyRef-Local) | | | -| foreign_ty_ref | [TyRef.Foreign](#lambdabuffers-compiler-TyRef-Foreign) | | | - - - - - - - - -### TyRef.Foreign -Foreign type reference. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_name | [TyName](#lambdabuffers-compiler-TyName) | | Foreign module type name. | -| module_name | [ModuleName](#lambdabuffers-compiler-ModuleName) | | Foreign module name. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyRef.Local -Local type reference. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ty_name | [TyName](#lambdabuffers-compiler-TyName) | | Local module type name. | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - -### TyVar -Type variable - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| var_name | [VarName](#lambdabuffers-compiler-VarName) | | Variable name. | - - - - - - - - -### Tys -A list of type terms useful for debugging - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| ties | [Ty](#lambdabuffers-compiler-Ty) | repeated | | - - - - - - - - -### VarName -Type variable name - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | | Name ::= [a-z]+ | -| source_info | [SourceInfo](#lambdabuffers-compiler-SourceInfo) | | Source information. | - - - - - - - - - - -### Kind.KindRef -A built-in kind. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| KIND_REF_UNSPECIFIED | 0 | Unspecified kind SHOULD be inferred by the Compiler. | -| KIND_REF_TYPE | 1 | A `Type` kind (also know as `*` in Haskell) built-in. | - - - - - - - - - - -## Scalar Value Types - -| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | -| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- | -| double | | double | double | float | float64 | double | float | Float | -| float | | float | float | float | float32 | float | float | Float | -| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) | -| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) | -| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) | -| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum | -| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | -| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | -| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | - - diff --git a/docs/examples/Document.lbf b/docs/examples/Document.lbf new file mode 100644 index 00000000..8393ed08 --- /dev/null +++ b/docs/examples/Document.lbf @@ -0,0 +1,48 @@ +module Document + +-- Author +sum Author = Ivan | Jovan | Savo + +-- Reviewer +sum Reviewer = Bob | Alice + +-- Document +record Document a = { + author : Author, + reviewers : List Reviewer, + content : Chapter a + } + +-- Chapter +record Chapter a = { + content : a, + subChapters : List (Chapter a) + } + +-- Some actual content +sum RichContent = Image Image String | Gif Gif String | Text String + +sum Image = FunnyImage | BoringImage + +sum Gif = FunnyGif | InspiringGif + +-- Rich document + +prod RichDocument = (Document RichContent) + +-- # Some basic types + +-- ## We need a list type +sum List a = Nil | Cons a (List a) + +-- ## We need a Char type that is either a letter, number or punctuation +sum Char = Letter Letter | Number Number | Punctuation Punctuation + +sum Letter = A | B | C + +sum Number = Num0 | Num1 | Num2 + +sum Punctuation = Dot | Question + +-- ## String +prod String = (List Char) \ No newline at end of file diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 00000000..3958b98f --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,72 @@ +# Getting started + +## Installing Nix + +This repository relies heavily on the [Nix Package +Manager](https://nixos.org/download.html) for both development and package +distribution. + +To install run the following command: + +```sh +sh <(curl -L https://nixos.org/nix/install) --daemon +``` + +and follow the instructions. + +```sh +$ nix --version +nix (Nix) 2.8.0 +``` + +> NOTE: The repository should work with Nix version greater or equal to 2.8.0. + +Make sure to enable [Nix Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes) +and IFD by editing either `~/.config/nix/nix.conf` or `/etc/nix/nix.conf` on +your machine and add the following configuration entries: + +```yaml +experimental-features = nix-command flakes +allow-import-from-derivation = true +``` + +Optionally, to improve build speed, it is possible to set up a binary caches +maintained by IOHK and Plutonomicon by setting additional configuration entries: + +```yaml +substituters = https://cache.nixos.org https://iohk.cachix.org https://cache.iog.io https://public-plutonomicon.cachix.org +trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= public-plutonomicon.cachix.org-1:3AKJMhCLn32gri1drGuaZmFrmnue+KkKrhhubQk/CWc= +``` + +## Building and development + +To facilitate seamlessly moving between directories and associated Nix +development shells we use [direnv](https://direnv.net) and +[nix-direnv](https://github.com/nix-community/nix-direnv): + +To install both using `nixpkgs`: + +```sh +nix profile install nixpkgs#direnv +nix profile install nixpkgs#nix-direnv +``` + +Your shell and editors should pick up on the `.envrc` files in different +directories and prepare the environment accordingly. Use `direnv allow` to +enable the direnv environment and `direnv reload` to reload it when necessary. + +Additionally, throughout the repository one can use: + +```sh +$ pre-commit run --all +cabal-fmt............................................(no files to check)Skipped +fourmolu.................................................................Passed +hlint....................................................................Passed +markdownlint.............................................................Passed +nix-linter...............................................................Passed +nixpkgs-fmt..............................................................Passed +shellcheck...........................................(no files to check)Skipped +typos....................................................................Passed +``` + +To run all the code quality tooling specified in the [pre-commit-check config file](../pre-commit.nix) diff --git a/docs/haskell.md b/docs/haskell.md new file mode 100644 index 00000000..b8a4f643 --- /dev/null +++ b/docs/haskell.md @@ -0,0 +1,198 @@ +# LambdaBuffers to Haskell + +Let's take a look at how LambdaBuffers modules map into Haskell modules and how +LambdaBuffers type definitions map into Haskell type definitions. + +Note that in this chapter we work with a 'pure' LambdaBuffers module, no +`opaque`s or type clasess, to demonstrate how pure type definition mapping +works. + +We'll use the `lbf-to-haskell` CLI tool which is just a convenient wrapper over +the raw `lbf` CLI. We can get this tool by either loading the LambdaBuffers Nix +environment that comes packaged with all the CLI tools: + +```shell +$ nix develop github:mlabs-haskell/lambda-buffers#lb +$ lb +lbc lbf lbg lbg-purescript lbg-haskelll lbf-to-purescript lbf-to-haskell +``` + +Or we can simply just refer directly to the `lbf-to-haskell` CLI by `nix run +github:mlabs-haskell/lambda-buffers#lbf-to-haskell`. + +In this chapter, we're going to use the latter option. + +Let's now use `lbf-to-haskell` to process the + +[Document.lbf](examples/Document.lbf) schema + +```purescript +module Document + +-- Author +sum Author = Ivan | Jovan | Savo + +-- Reviewer +sum Reviewer = Bob | Alice + +-- Document +record Document a = { + author : Author, + reviewers : List Reviewer, + content : Chapter a + } + +-- Chapter +record Chapter a = { + content : a, + subChapters : List (Chapter a) + } + +-- Some actual content +sum RichContent = Image Image String | Gif Gif String | Text String + +sum Image = FunnyImage | BoringImage + +sum Gif = FunnyGif | InspiringGif + +-- Rich document + +prod RichDocument = (Document RichContent) + +-- # Some basic types + +-- ## We need a list type +sum List a = Nil | Cons a (List a) + +-- ## We need a Char type that is either a letter, number or punctuation +sum Char = Letter Letter | Number Number | Punctuation Punctuation + +sum Letter = A | B | C + +sum Number = Num0 | Num1 | Num2 + +sum Punctuation = Dot | Question + +-- ## String +prod String = (List Char) +``` + +```shell +$ nix run github:mlabs-haskell/lambda-buffers#lbf-to-haskell -- Document.lbf +$ find autogen/ +autogen/ +autogen/build.json +autogen/LambdaBuffers +autogen/LambdaBuffers/Document.hs +$ ghc autogen/LambdaBuffers/Document.hs +[1 of 1] Compiling LambdaBuffers.Document ( autogen/LambdaBuffers/Document.hs, autogen/LambdaBuffers/Document.o ) +``` + +As we can see the `autogen` directory has been created that contains the generated Haskell modules. +Note the `autogen/build.json` file as it contains all the necessary Hackage dependencies the generated module needs in order to be properly compiled by GHC. + +The outputted Haskell module in `autogen/LambdaBuffers/Document.hs`: + +```haskell +module LambdaBuffers.Document + ( Author (..), + Chapter (..), + Char (..), + Document (..), + Gif (..), + Image (..), + Letter (..), + List (..), + Number (..), + Punctuation (..), + Reviewer (..), + RichContent (..), + RichDocument (..), + String (..), + ) +where + +import qualified Prelude + +data Author = Author'Ivan | Author'Jovan | Author'Savo deriving (Prelude.Show) + +data Chapter a = Chapter + { chapter'content :: a, + chapter'subChapters :: List (Chapter a) + } + deriving (Prelude.Show) + +data Char + = Char'Letter Letter + | Char'Number Number + | Char'Punctuation Punctuation + deriving (Prelude.Show) + +data Document a = Document + { document'author :: Author, + document'reviewers :: List Reviewer, + document'content :: Chapter a + } + deriving (Prelude.Show) + +data Gif = Gif'FunnyGif | Gif'InspiringGif deriving (Prelude.Show) + +data Image = Image'FunnyImage | Image'BoringImage deriving (Prelude.Show) + +data Letter = Letter'A | Letter'B | Letter'C deriving (Prelude.Show) + +data List a = List'Nil | List'Cons a (List a) deriving (Prelude.Show) + +data Number = Number'Num0 | Number'Num1 | Number'Num2 deriving (Prelude.Show) + +data Punctuation + = Punctuation'Dot + | Punctuation'Question + deriving (Prelude.Show) + +data Reviewer = Reviewer'Bob | Reviewer'Alice deriving (Prelude.Show) + +data RichContent + = RichContent'Image Image String + | RichContent'Gif Gif String + | RichContent'Text String + deriving (Prelude.Show) + +newtype RichDocument = RichDocument (Document RichContent) deriving (Prelude.Show) + +newtype String = String (List Char) deriving (Prelude.Show) +``` + +## Sum types + +The types `Author`, `Reviewer`, `RichContent`, `Image`, `Gif`, `List`, `Char`, +`Letter`, `Number` and `Punctuation` have been declared as sum types in the +LamdaBuffers schema using the `sum` keyword. + +As we can see, notihing too surprising here, all the `sum` types become `data` +in haskell. + +The only thing to notice is that the type name was prepended with `'` (single +quote) to the defined constructor names as to make sure they are unique. + +## Product types + +The types `RichDocument` and `String` have been declared as product types in the +LamdaBuffers schema using the `prod` keyword. + +They become Haskell `newtype` if they have a single type in their body, otherwise they are `data`. + +Note that the constructor has the same name as the type. + +## Record types + +The types `Document` and `Chapter` have been declared as record types in the +LamdaBuffers schema using the `record` keyword. + +Like with product types, they become Haskell `newtype` if they have a single +type in their body, otherwise they are `data`. + +Also like with product types, the constructor has the same name as the type. + +The field names, similar to sum constructor names, are prepended with the +lowercased named of the type with a single quote (`'`) to maintain uniqueness. diff --git a/docs/introduction.md b/docs/introduction.md new file mode 100644 index 00000000..cb6326ae --- /dev/null +++ b/docs/introduction.md @@ -0,0 +1,42 @@ +# Lambda Buffers introduction + +![LambdaBuffers banner](./images/lambda-buffers-banner.png) + +_LambdaBuffers_ is a schema language (similar to ProtoBuffers, ADL, ASN.1, JSON +Schema, etc.) and associated code generation toolkit. The goal of this project +is to provide developers tools to define algebraic data types in a +language-agnostic format such that shared data types can be declared in one +place while maintaining compatibility across a plethora of supported languages. + +Users may refer to the [comparison matrix](./comparison-matrix.md) for an +in-depth comparison of LambdaBuffers' features against the feature-set of other +popular schema-languages. + +At a glance, you may wish to choose LambdaBuffers instead of one of its +competitors if your project requires: + + 1. _Parameterized Data Types_ (aka. type functions): Unlike ProtoBuffers or + JSON Schema, LambdaBuffers allows users to define algebraic data types which + take type variable arguments. If your project's domain is most accurately + represented by parameterized data types, LamdaBuffers may be a good choice + for your needs. + + 2. _Opaque Types_: Almost every competing schema language provides users a + fixed set of builtin or primitive types, which are handled in a special + manner by the code generation and cannot be extended. LambdaBuffers, by + contrast, allows users to add their own builtin types and extend the + existing code generation framework to handle those builtins in a manner + intended by the users. There are no _special_ primitive types in + LambdaBuffers; a user-defined primitive type is defined in exactly the same + way (i.e. as an `opaque` type) as a LambdaBuffers "builtin". + + 3. _Typeclass Support_: While nearly every schema language supports generating + type definitions in supported target languages, to our knowledge no schema + language supports generating commonly used functions that operate on those + types. Unlike other schema languages, LambdaBuffers supports code generation + for _typeclass instances_ (or the equivalent in languages that lack support + for typeclasses) to reduce the amount of boilerplate required to + productively make use of the generated types. While LambdaBuffers is still a + work-in-progress, we expect that, upon completion, an extensive test suite + will provide a high degree of assurance that the instances/methods generated + by the LamdaBuffers code generator behave identically. diff --git a/docs/purescript.md b/docs/purescript.md new file mode 100644 index 00000000..20b207fc --- /dev/null +++ b/docs/purescript.md @@ -0,0 +1,227 @@ +# LambdaBuffers to Purescript + +Let's take a look at how LambdaBuffers modules map into Purescript modules and how +LambdaBuffers type definitions map into Purescript type definitions. + +Note that in this chapter we work with a 'pure' LambdaBuffers module, no +`opaque`s or type clasess, to demonstrate how pure type definition mapping +works. + +We'll use the `lbf-to-purescript` CLI tool which is just a convenient wrapper over +the raw `lbf` CLI. We can get this tool by either loading the LambdaBuffers Nix +environment that comes packaged with all the CLI tools: + +```shell +$ nix develop github:mlabs-purescript/lambda-buffers#lb +$ lb +lbc lbf lbg lbg-purescript lbg-haskelll lbf-to-purescript lbf-to-haskell +``` + +Or we can simply just refer directly to the `lbf-to-purescript` CLI by `nix run +github:mlabs-purescript/lambda-buffers#lbf-to-purescript`. + +In this chapter, we're going to use the latter option. + +Let's now use `lbf-to-purescript` to process the + +[Document.lbf](examples/Document.lbf) schema + +```purescript +module Document + +-- Author +sum Author = Ivan | Jovan | Savo + +-- Reviewer +sum Reviewer = Bob | Alice + +-- Document +record Document a = { + author : Author, + reviewers : List Reviewer, + content : Chapter a + } + +-- Chapter +record Chapter a = { + content : a, + subChapters : List (Chapter a) + } + +-- Some actual content +sum RichContent = Image Image String | Gif Gif String | Text String + +sum Image = FunnyImage | BoringImage + +sum Gif = FunnyGif | InspiringGif + +-- Rich document + +prod RichDocument = (Document RichContent) + +-- # Some basic types + +-- ## We need a list type +sum List a = Nil | Cons a (List a) + +-- ## We need a Char type that is either a letter, number or punctuation +sum Char = Letter Letter | Number Number | Punctuation Punctuation + +sum Letter = A | B | C + +sum Number = Num0 | Num1 | Num2 + +sum Punctuation = Dot | Question + +-- ## String +prod String = (List Char) +``` + +```shell +$ nix run github:mlabs-purescript/lambda-buffers#lbf-to-purescript -- Document.lbf +$ find autogen/ +autogen/ +autogen/build.json +autogen/LambdaBuffers +autogen/LambdaBuffers/Document.purs +``` + +As we can see the `autogen` directory has been created that contains the generated Purescript modules. +Note the `autogen/build.json` file as it contains all the necessary dependencies the generated module needs in order to be properly compiled by `purs` compiler. + +The outputted Purescript module in `autogen/LambdaBuffers/Document.hs`: + +```purescript +module LambdaBuffers.Document (Author(..) + , Chapter(..) + , Char(..) + , Document(..) + , Gif(..) + , Image(..) + , Letter(..) + , List(..) + , Number(..) + , Punctuation(..) + , Reviewer(..) + , RichContent(..) + , RichDocument(..) + , String(..)) where + +import Data.Generic.Rep as Data.Generic.Rep +import Data.Newtype as Data.Newtype +import Data.Show as Data.Show +import Data.Show.Generic as Data.Show.Generic + + +data Author = Author'Ivan | Author'Jovan | Author'Savo +derive instance Data.Generic.Rep.Generic Author _ +instance Data.Show.Show Author where + show = Data.Show.Generic.genericShow + +newtype Chapter a = Chapter { content :: a, subChapters :: List (Chapter a)} +derive instance Data.Newtype.Newtype (Chapter a) _ +derive instance Data.Generic.Rep.Generic (Chapter a) _ +instance (Data.Show.Show a) => Data.Show.Show (Chapter a) where + show = Data.Show.Generic.genericShow + +data Char = Char'Letter Letter + | Char'Number Number + | Char'Punctuation Punctuation +derive instance Data.Generic.Rep.Generic Char _ +instance Data.Show.Show Char where + show = Data.Show.Generic.genericShow + +newtype Document a = Document { author :: Author + , reviewers :: List Reviewer + , content :: Chapter a} +derive instance Data.Newtype.Newtype (Document a) _ +derive instance Data.Generic.Rep.Generic (Document a) _ +instance (Data.Show.Show a) => Data.Show.Show (Document a) where + show = Data.Show.Generic.genericShow + +data Gif = Gif'FunnyGif | Gif'InspiringGif +derive instance Data.Generic.Rep.Generic Gif _ +instance Data.Show.Show Gif where + show = Data.Show.Generic.genericShow + +data Image = Image'FunnyImage | Image'BoringImage +derive instance Data.Generic.Rep.Generic Image _ +instance Data.Show.Show Image where + show = Data.Show.Generic.genericShow + +data Letter = Letter'A | Letter'B | Letter'C +derive instance Data.Generic.Rep.Generic Letter _ +instance Data.Show.Show Letter where + show = Data.Show.Generic.genericShow + +data List a = List'Nil | List'Cons a (List a) +derive instance Data.Generic.Rep.Generic (List a) _ +instance (Data.Show.Show a) => Data.Show.Show (List a) where + show = Data.Show.Generic.genericShow + +data Number = Number'Num0 | Number'Num1 | Number'Num2 +derive instance Data.Generic.Rep.Generic Number _ +instance Data.Show.Show Number where + show = Data.Show.Generic.genericShow + +data Punctuation = Punctuation'Dot | Punctuation'Question +derive instance Data.Generic.Rep.Generic Punctuation _ +instance Data.Show.Show Punctuation where + show = Data.Show.Generic.genericShow + +data Reviewer = Reviewer'Bob | Reviewer'Alice +derive instance Data.Generic.Rep.Generic Reviewer _ +instance Data.Show.Show Reviewer where + show = Data.Show.Generic.genericShow + +data RichContent = RichContent'Image Image String + | RichContent'Gif Gif String + | RichContent'Text String +derive instance Data.Generic.Rep.Generic RichContent _ +instance Data.Show.Show RichContent where + show = Data.Show.Generic.genericShow + +newtype RichDocument = RichDocument (Document RichContent) +derive instance Data.Newtype.Newtype RichDocument _ +derive instance Data.Generic.Rep.Generic RichDocument _ +instance Data.Show.Show RichDocument where + show = Data.Show.Generic.genericShow + +newtype String = String (List Char) +derive instance Data.Newtype.Newtype String _ +derive instance Data.Generic.Rep.Generic String _ +instance Data.Show.Show String where + show = Data.Show.Generic.genericShow +``` + +## Sum types + +The types `Author`, `Reviewer`, `RichContent`, `Image`, `Gif`, `List`, `Char`, +`Letter`, `Number` and `Punctuation` have been declared as sum types in the +LamdaBuffers schema using the `sum` keyword. + +As we can see, notihing too surprising here, all the `sum` types become `data` +in Purescript. + +The only thing to notice is that the type name was prepended with `'` (single +quote) to the defined constructor names as to make sure they are unique. + +## Product types + +The types `RichDocument` and `String` have been declared as product types in the +LamdaBuffers schema using the `prod` keyword. + +They become Purescript `newtype` if they have a single type in their body, otherwise they are `data`. + +Note that the constructor has the same name as the type. + +## Record types + +The types `Document` and `Chapter` have been declared as record types in the +LamdaBuffers schema using the `record` keyword. + +They always become Purescript `newtype`, and wrapped within is a Purescript +record type with the fields named exactly like they are named in the +LambdaBuffers source module. + +Also like with product types, the constructor has the same name as the type. diff --git a/extras/lbf-haskell-plutus.nix b/extras/lbf-haskell-plutus.nix index a216ded9..0e6515ee 100644 --- a/extras/lbf-haskell-plutus.nix +++ b/extras/lbf-haskell-plutus.nix @@ -18,5 +18,3 @@ lbf: lbg-haskell: lbfHaskellOpts: (import ./lbf-haskell.nix) lbf lbg-haskell (ut } lbfHaskellOpts ) - - diff --git a/flake.nix b/flake.nix index 8fb1c5f6..445740a6 100644 --- a/flake.nix +++ b/flake.nix @@ -19,6 +19,7 @@ imports = [ (import ./hercules-ci.nix) (import ./pre-commit.nix) + (import ./docs/build.nix) ]; debug = true; systems = [ "x86_64-linux" ]; @@ -61,17 +62,11 @@ inherit pkgs commonTools shellHook; }; - # Docs env - - docsDevShell = import ./docs/build.nix { - inherit pkgs commonTools shellHook; - }; - # Protos build pbnix-lib = protobufs-nix.lib.${system}; - protosBuild = import ./lambda-buffers-proto/build.nix { + protosBuild = import ./api/build.nix { inherit pkgs pbnix-lib commonTools shellHook; }; @@ -93,7 +88,7 @@ compilerBuild = buildAbstraction { import-location = ./lambda-buffers-compiler/build.nix; - additional = { inherit (protosBuild) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; }; + additional = { inherit (protosBuild.packages) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; }; }; compilerFlake = flakeAbstraction compilerBuild; @@ -102,7 +97,7 @@ codegenBuild = buildAbstraction { import-location = ./lambda-buffers-codegen/build.nix; additional = { - inherit (protosBuild) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; + inherit (protosBuild.packages) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; lambda-buffers-compiler = ./lambda-buffers-compiler; }; }; @@ -113,7 +108,7 @@ frontendBuild = buildAbstraction { import-location = ./lambda-buffers-frontend/build.nix; additional = { - inherit (protosBuild) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; + inherit (protosBuild.packages) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; lambda-buffers-compiler = ./lambda-buffers-compiler; inherit (clis) lbc lbg lbg-haskell lbg-purescript; }; @@ -132,11 +127,36 @@ lbg-purescript = pkgs.writeShellScriptBin "lbg-purescript" '' ${lbg}/bin/lbg gen-purescript $@ ''; - lbf = pkgs.writeScriptBin "lbf" '' + lbf = pkgs.writeShellScriptBin "lbf" '' export LB_CODEGEN=${lbg-haskell}/bin/lbg-haskell; export LB_COMPILER=${lbc}/bin/lbc; ${lbf-pure}/bin/lbf $@ ''; + lbf-to-haskell = pkgs.writeShellScriptBin "lbf-to-haskell" '' + export LB_COMPILER=${lbc}/bin/lbc; + + ${lbf-pure}/bin/lbf build --gen ${lbg-haskell}/bin/lbg-haskell $@ + ''; + lbf-to-haskell-prelude = pkgs.writeShellScriptBin "lbf-to-haskell-prelude" '' + export LB_COMPILER=${lbc}/bin/lbc; + + ${lbf-pure}/bin/lbf build --import-path ${./libs/lbf-prelude} \ + --gen-class Prelude.Eq --gen-class Prelude.Json \ + --gen ${lbg-haskell}/bin/lbg-haskell $@ + ''; + lbf-to-purescript = pkgs.writeShellScriptBin "lbf-to-purescript" '' + export LB_COMPILER=${lbc}/bin/lbc; + + ${lbf-pure}/bin/lbf build --gen ${lbg-purescript}/bin/lbg-purescript $@ + ''; + lbf-to-purescript-prelude = pkgs.writeShellScriptBin "lbf-to-purescript-prelude" '' + export LB_COMPILER=${lbc}/bin/lbc; + + ${lbf-pure}/bin/lbf build --import-path ${./libs/lbf-prelude} \ + --gen-class Prelude.Eq --gen-class Prelude.Json \ + --gen ${lbg-purescript}/bin/lbg-purescript $@ + ''; + }; # LambdaBuffers environment @@ -306,26 +326,23 @@ rec { # Standard flake attributes - packages = { - inherit (protosBuild) lambda-buffers-lang-hs-pb lambda-buffers-compiler-hs-pb lambda-buffers-codegen-hs-pb; - } - // compilerFlake.packages - // frontendFlake.packages - // codegenFlake.packages - // lbrPreludeHsFlake.packages - // lbrPreludePurs.packages - // lbrPlutusHsFlake.packages - // lbrPlutusPurs.packages - // lbtPreludeHsFlake.packages - // lbtPreludePursFlake.packages - // lbtPlutusHsFlake.packages - // lbtPlutusPursFlake.packages - // clis - // lbfLibs; + packages = protosBuild.packages + // compilerFlake.packages + // frontendFlake.packages + // codegenFlake.packages + // lbrPreludeHsFlake.packages + // lbrPreludePurs.packages + // lbrPlutusHsFlake.packages + // lbrPlutusPurs.packages + // lbtPreludeHsFlake.packages + // lbtPreludePursFlake.packages + // lbtPlutusHsFlake.packages + // lbtPlutusPursFlake.packages + // clis + // lbfLibs; devShells = rec { dev-experimental = experimentalDevShell; - dev-docs = docsDevShell; dev-protos = protosBuild.devShell; dev-compiler = compilerFlake.devShell; dev-frontend = frontendFlake.devShell; diff --git a/hercules-ci.nix b/hercules-ci.nix index 91e26fdc..228b0f66 100644 --- a/hercules-ci.nix +++ b/hercules-ci.nix @@ -17,11 +17,8 @@ }; }; hercules-ci.github-pages.branch = "main"; - perSystem = { pkgs, ... }: { - hercules-ci.github-pages.settings.contents = pkgs.runCommand "lambda-buffers-book" - { - buildInputs = [ pkgs.mdbook ]; - } "mdbook build ${self.outPath}/docs --dest-dir $out"; + perSystem = { pkgs, config, ... }: { + hercules-ci.github-pages.settings.contents = config.packages.lambda-buffers-book; }; herculesCI.ciSystems = [ "x86_64-linux" ]; diff --git a/lambda-buffers-proto/build.nix b/lambda-buffers-proto/build.nix deleted file mode 100644 index aedf3a02..00000000 --- a/lambda-buffers-proto/build.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ pkgs, pbnix-lib, commonTools, shellHook }: -rec { - devShell = pkgs.mkShell { - name = "protos-env"; - buildInputs = [ - pkgs.protobuf - pkgs.haskellPackages.proto-lens-protoc - pkgs.protoc-gen-doc - ] ++ builtins.attrValues commonTools; - - inherit shellHook; - }; - - lambda-buffers-lang-hs-pb = pbnix-lib.haskellProto { - inherit pkgs; - src = ./.; - proto = "lang.proto"; - cabalPackageName = "lambda-buffers-lang-pb"; - }; - - lambda-buffers-compiler-hs-pb = pbnix-lib.haskellProto { - inherit pkgs; - src = ./.; - proto = "compiler.proto"; - cabalBuildDepends = [ lambda-buffers-lang-hs-pb ]; - cabalPackageName = "lambda-buffers-compiler-pb"; - }; - - lambda-buffers-codegen-hs-pb = pbnix-lib.haskellProto { - inherit pkgs; - src = ./.; - proto = "codegen.proto"; - cabalBuildDepends = [ lambda-buffers-lang-hs-pb ]; - cabalPackageName = "lambda-buffers-codegen-pb"; - }; - -} diff --git a/lambda-buffers-proto/run.sh b/lambda-buffers-proto/run.sh deleted file mode 100755 index 24d8357c..00000000 --- a/lambda-buffers-proto/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -protoc --plugin=`which protoc-gen-doc` compiler.proto --doc_out=../docs/ --doc_opt=markdown,compiler-api.md -echo "" >> ../docs/compiler-api.md