hydra-0.15.0: src/main/haskell/Hydra/Sources/Coq/Language.hs
{-# LANGUAGE FlexibleContexts #-}
-- | Language constraints for Coq code generation.
module Hydra.Sources.Coq.Language where
-- Standard imports for term-level sources outside of the kernel
import Hydra.Kernel
import Hydra.Sources.Libraries
import Hydra.Dsl.Meta.Lib.Strings as Strings
import Hydra.Dsl.Meta.Phantoms as Phantoms
import qualified Hydra.Dsl.Meta.Lib.Lists as Lists
import qualified Hydra.Dsl.Meta.Lib.Sets as Sets
import qualified Hydra.Dsl.Coders as Coders
import qualified Hydra.Dsl.Meta.Core as Core
import qualified Hydra.Dsl.Meta.Variants as Variants
import qualified Hydra.Sources.Kernel.Terms.Constants as Constants
import qualified Hydra.Sources.Kernel.Terms.Formatting as Formatting
import qualified Hydra.Sources.Kernel.Types.All as KernelTypes
import qualified Hydra.Sources.Coq.Syntax as CoqSyntax
import Prelude hiding ((++))
import qualified Data.List as DL
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Maybe as Y
import Hydra.Ast
define :: String -> TTerm a -> TTermDefinition a
define = definitionInModule module_
ns :: Namespace
ns = Namespace "hydra.coq.language"
module_ :: Module
module_ = Module {
moduleNamespace = ns,
moduleDefinitions = definitions,
moduleTermDependencies = [Constants.ns, Formatting.ns],
moduleTypeDependencies = (CoqSyntax.ns:KernelTypes.kernelTypesNamespaces),
moduleDescription = Just "Language constraints for Coq code generation"}
where
definitions = [
toDefinition coqLanguage,
toDefinition coqReservedWords,
toDefinition coqStrippedReservedWords]
-- | Language constraints for Coq.
-- Coq's type system (CIC) is a strict superset of System F, so it supports all Hydra features.
coqLanguage :: TTermDefinition Language
coqLanguage = define "coqLanguage" $ lets [
"eliminationVariants">: Sets.fromList $ list [
Variants.eliminationVariantRecord,
Variants.eliminationVariantUnion,
Variants.eliminationVariantWrap],
"literalVariants">: Sets.fromList $ list [
Variants.literalVariantBoolean,
Variants.literalVariantFloat,
Variants.literalVariantInteger,
Variants.literalVariantString],
"floatTypes">: Sets.fromList $ list [
Core.floatTypeFloat64],
"functionVariants">: Sets.fromList $ list [
Variants.functionVariantElimination,
Variants.functionVariantLambda],
"integerTypes">: Sets.fromList $ list [
Core.integerTypeBigint],
"termVariants">: Sets.fromList $ list [
Variants.termVariantApplication,
Variants.termVariantEither,
Variants.termVariantCases,
Variants.termVariantLambda,
Variants.termVariantProject,
Variants.termVariantUnwrap,
Variants.termVariantTypeApplication,
Variants.termVariantTypeLambda,
Variants.termVariantLet,
Variants.termVariantList,
Variants.termVariantLiteral,
Variants.termVariantMap,
Variants.termVariantMaybe,
Variants.termVariantPair,
Variants.termVariantRecord,
Variants.termVariantSet,
Variants.termVariantInject,
Variants.termVariantUnit,
Variants.termVariantVariable,
Variants.termVariantWrap],
"typeVariants">: Sets.fromList $ list [
Variants.typeVariantAnnotated,
Variants.typeVariantApplication,
Variants.typeVariantEither,
Variants.typeVariantForall,
Variants.typeVariantFunction,
Variants.typeVariantList,
Variants.typeVariantLiteral,
Variants.typeVariantMap,
Variants.typeVariantMaybe,
Variants.typeVariantPair,
Variants.typeVariantRecord,
Variants.typeVariantSet,
Variants.typeVariantUnion,
Variants.typeVariantUnit,
Variants.typeVariantVariable,
Variants.typeVariantVoid,
Variants.typeVariantWrap],
"typePredicate">: constant true] $
Coders.language
(Coders.languageName_ $ string "hydra.coq")
(Coders.languageConstraints_
(var "eliminationVariants")
(var "literalVariants")
(var "floatTypes")
(var "functionVariants")
(var "integerTypes")
(var "termVariants")
(var "typeVariants")
(var "typePredicate"))
-- | Reserved words that must be renamed when used as Coq variable or binding names.
-- This set is kept narrower than the full Coq lexicon: it includes only the tokens
-- that actually clash with Coq variable-name usage (Gallina and vernacular keywords)
-- plus a few stdlib names that appear as Hydra-generated lambda parameter names.
coqReservedWords :: TTermDefinition (S.Set String)
coqReservedWords = define "coqReservedWords" $
Sets.fromList $ list $ fmap string reservedWords
where
reservedWords = [
-- Gallina and vernacular keywords
"as", "at", "cofix", "do", "else", "end", "exists", "exists2",
"fix", "for", "forall", "fun", "if", "IF", "in", "let", "match",
"mod", "open", "Prop", "return", "Set", "then", "Type", "using",
"where", "with",
"Axiom", "Class", "Coercion", "Context", "Definition", "Fixpoint",
"Hypothesis", "Inductive", "Instance", "Lemma", "Module", "Notation",
"Proof", "Qed", "Record", "Require", "Import", "Section", "End",
"Theorem", "Example", "Variable", "Variables",
-- Coq stdlib names that appear as Hydra-generated lambda parameter names
"cons", "pair", "nil",
-- Coq stdlib type constructors that can be shadowed by local let bindings,
-- causing cryptic "Non-functional construction" errors when subsequent
-- code tries to use the type.
"list", "option", "prod", "sum", "unit", "bool", "nat", "string",
-- Names that collide with Hydra kernel function names after namespace
-- stripping (e.g., hydra.show.core.term, hydra.show.core.type).
"term", "literal", "graph", "element"]
-- | Reserved words that must be renamed when they appear as a stripped-local
-- form of a cross-module Hydra reference. This set is used only by
-- `resolveQualifiedName` when it converts a `hydra.<ns>.<x>` reference to its
-- short form. It is strictly narrower than `coqReservedWords` — in particular
-- it does *not* include `term`, `literal`, `element`, whose cross-module
-- disambiguation is handled by the ambiguous-names mechanism, not by
-- underscore-escaping. It is narrower at the lambda-parameter side too, but
-- that set is tracked separately via `coqReservedWords`.
coqStrippedReservedWords :: TTermDefinition (S.Set String)
coqStrippedReservedWords = define "coqStrippedReservedWords" $
Sets.fromList $ list $ fmap string reservedWords
where
reservedWords = [
-- Gallina and vernacular keywords
"as", "at", "cofix", "do", "else", "end", "exists", "exists2",
"fix", "for", "forall", "fun", "if", "IF", "in", "let", "match",
"mod", "Prop", "return", "Set", "then", "Type", "using",
"where", "with",
"Axiom", "Class", "Coercion", "Context", "Definition", "Fixpoint",
"Hypothesis", "Inductive", "Instance", "Lemma", "Module", "Notation",
"Proof", "Qed", "Record", "Require", "Import", "Section", "End",
"Theorem", "Example", "Variable", "Variables",
-- Coq stdlib type names
"bool", "nat", "list", "option", "prod", "sum", "unit",
"string", "String", "Empty_set",
-- Coq stdlib value constructors
"true", "false", "None", "Some", "nil", "cons", "pair",
"inl", "inr", "tt",
-- Hydra module name whose stripped form collides with generated
-- definition names.
"graph"]