From 519c0c0c71cdf7ce3dfc64b9781ab826760b3d94 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Mon, 14 Jun 2021 18:33:54 -0400 Subject: Extracted Licentia out of the standard library. --- licentia/commands.md | 26 ++ licentia/project.clj | 33 ++ licentia/source/program/licentia.lux | 85 +++++ licentia/source/program/licentia/document.lux | 47 +++ licentia/source/program/licentia/input.lux | 167 ++++++++++ licentia/source/program/licentia/license.lux | 62 ++++ .../source/program/licentia/license/addendum.lux | 28 ++ .../source/program/licentia/license/assurance.lux | 25 ++ .../source/program/licentia/license/black_list.lux | 31 ++ .../source/program/licentia/license/commercial.lux | 30 ++ .../source/program/licentia/license/copyright.lux | 8 + .../source/program/licentia/license/definition.lux | 240 ++++++++++++++ .../program/licentia/license/distribution.lux | 112 +++++++ .../source/program/licentia/license/extension.lux | 166 ++++++++++ licentia/source/program/licentia/license/grant.lux | 128 +++++++ .../source/program/licentia/license/liability.lux | 160 +++++++++ .../source/program/licentia/license/limitation.lux | 75 +++++ .../program/licentia/license/miscellaneous.lux | 106 ++++++ .../source/program/licentia/license/notice.lux | 33 ++ .../source/program/licentia/license/submission.lux | 26 ++ licentia/source/program/licentia/license/term.lux | 34 ++ licentia/source/program/licentia/license/time.lux | 15 + licentia/source/program/licentia/output.lux | 309 +++++++++++++++++ licentia/source/test/licentia.lux | 368 +++++++++++++++++++++ 24 files changed, 2314 insertions(+) create mode 100644 licentia/commands.md create mode 100644 licentia/project.clj create mode 100644 licentia/source/program/licentia.lux create mode 100644 licentia/source/program/licentia/document.lux create mode 100644 licentia/source/program/licentia/input.lux create mode 100644 licentia/source/program/licentia/license.lux create mode 100644 licentia/source/program/licentia/license/addendum.lux create mode 100644 licentia/source/program/licentia/license/assurance.lux create mode 100644 licentia/source/program/licentia/license/black_list.lux create mode 100644 licentia/source/program/licentia/license/commercial.lux create mode 100644 licentia/source/program/licentia/license/copyright.lux create mode 100644 licentia/source/program/licentia/license/definition.lux create mode 100644 licentia/source/program/licentia/license/distribution.lux create mode 100644 licentia/source/program/licentia/license/extension.lux create mode 100644 licentia/source/program/licentia/license/grant.lux create mode 100644 licentia/source/program/licentia/license/liability.lux create mode 100644 licentia/source/program/licentia/license/limitation.lux create mode 100644 licentia/source/program/licentia/license/miscellaneous.lux create mode 100644 licentia/source/program/licentia/license/notice.lux create mode 100644 licentia/source/program/licentia/license/submission.lux create mode 100644 licentia/source/program/licentia/license/term.lux create mode 100644 licentia/source/program/licentia/license/time.lux create mode 100644 licentia/source/program/licentia/output.lux create mode 100644 licentia/source/test/licentia.lux (limited to 'licentia') diff --git a/licentia/commands.md b/licentia/commands.md new file mode 100644 index 000000000..58ac36376 --- /dev/null +++ b/licentia/commands.md @@ -0,0 +1,26 @@ +## Build + +``` +## Develop +cd ~/lux/licentia/ \ +&& lein clean \ +&& lein lux auto build +``` + +## Test + +``` +## Develop +cd ~/lux/licentia/ \ +&& lein clean \ +&& lein lux auto test +``` + +## Run + +``` +## Re-generate Lux's license. +cd ~/lux/licentia/ \ +&& java -jar target/program.jar --input ../license.json --output ../license.txt +``` + diff --git a/licentia/project.clj b/licentia/project.clj new file mode 100644 index 000000000..97756c024 --- /dev/null +++ b/licentia/project.clj @@ -0,0 +1,33 @@ +(def version "0.6.0-SNAPSHOT") +(def repo "https://github.com/LuxLang/lux") +(def sonatype-releases "https://oss.sonatype.org/service/local/staging/deploy/maven2/") +(def sonatype-snapshots "https://oss.sonatype.org/content/repositories/snapshots/") + +(defproject com.github.luxlang/licentia #=(identity version) + :description "A program for producing free/open-source/reciprocal licenses." + + :url ~(str repo "/licentia") + :license {:name "Lux License v0.1.1" + :url ~(str repo "/blob/master/license.txt")} + + :repositories [["releases" ~sonatype-releases] + ["snapshots" ~sonatype-snapshots]] + :deploy-repositories [["releases" {:url ~sonatype-releases :creds :gpg}] + ["snapshots" {:url ~sonatype-snapshots :creds :gpg}]] + + :plugins [[com.github.luxlang/lein-luxc ~version]] + + :dependencies [[com.github.luxlang/luxc-jvm ~version] + [com.github.luxlang/stdlib ~version]] + + :pom-addition [:developers [:developer + [:name "Eduardo Julian"] + [:url "https://github.com/eduardoejp"]]] + :scm {:name "git" + :url ~(str repo ".git")} + :manifest {"lux" ~version} + + :source-paths ["source"] + :lux {:program "program/licentia" + :test "test/licentia"} + ) diff --git a/licentia/source/program/licentia.lux b/licentia/source/program/licentia.lux new file mode 100644 index 000000000..57ed832e5 --- /dev/null +++ b/licentia/source/program/licentia.lux @@ -0,0 +1,85 @@ +## The licenses produced by this program are inspired by: +## Apache License (Version 2.0): https://www.apache.org/licenses/LICENSE-2.0 +## Mozilla Public License (Version 2.0): https://www.mozilla.org/en-US/MPL/2.0/ +## MIT/Expat License: https://opensource.org/licenses/MIT +## BSD licenses: https://en.wikipedia.org/wiki/BSD_licenses +## Commons Clause: https://commonsclause.com/ +## Reciprocal Public License 1.5 (RPL-1.5): https://opensource.org/licenses/RPL-1.5 +## The Parity Public License: https://licensezero.com/licenses/parity +## The Charity Public License: https://licensezero.com/licenses/charity +## Lerna black-list: https://github.com/lerna/lerna/pull/1616 +## Common Public Attribution License Version 1.0 (CPAL-1.0): https://opensource.org/licenses/CPAL-1.0 +## Eclipse Public License v2.0: https://www.eclipse.org/legal/epl-2.0/ + +(.module: + [lux #* + [ffi (#+ import:)] + [program (#+ program:)] + ["." debug] + [abstract + [monad (#+ do)]] + [control + [remember (#+ to_do)] + ["." io (#+ IO) ("#\." monad)] + ["." try (#+ Try)] + ["." parser + ["<.>" cli] + ["<.>" json]] + [security + ["!" capability]]] + [data + ["." maybe] + ["." text + ["%" format (#+ format)] + [encoding + ["." utf8]]] + [format + ["." json]]] + [world + ["." file (#+ Path File)]]] + ["." / #_ + ["#." input] + ["#." output]]) + +(with_expansions [ "2022-04-01"] + (to_do "Replace _.work with _.covered_work or _.licensed_work") + (to_do "Create a short notice to add as a comment to each file in the _.work")) + +(import: java/lang/String + ["#::." + (trim [] java/lang/String)]) + +(def: default_output_file "LICENSE") + +(def: (success_message output) + (-> Path Text) + (format "Your license has been made!" text.new_line + "Check the file " output ".")) + +(program: [{input (.named "--input" .any)} + {output (parser.default ..default_output_file + (.named "--output" .any))}] + (do io.monad + [?done (: (IO (Try Any)) + (do (try.with io.monad) + [file (!.use (\ file.default file) [input]) + blob (!.use (\ file content) []) + document (io\wrap (do {! try.monad} + [raw_json (\ utf8.codec decode blob) + json (|> raw_json + (:coerce java/lang/String) + java/lang/String::trim + (:coerce Text) + (\ json.codec decode))] + (|> json + (.run /input.license) + (\ ! map /output.license)))) + output_file (: (IO (Try (File IO))) + (file.get_file io.monad file.default output))] + (!.use (\ output_file over_write) (\ utf8.codec encode document))))] + (wrap (debug.log! (case ?done + (#try.Success _) + (success_message output) + + (#try.Failure message) + message))))) diff --git a/licentia/source/program/licentia/document.lux b/licentia/source/program/licentia/document.lux new file mode 100644 index 000000000..95c14e231 --- /dev/null +++ b/licentia/source/program/licentia/document.lux @@ -0,0 +1,47 @@ +(.module: + [lux (#- or and) + [data + ["." text + ["%" format (#+ format)]] + [collection + ["." list ("#\." functor)]]]]) + +(def: #export (quote text) + (-> Text Text) + (format text.double_quote text text.double_quote)) + +(def: #export (block content) + (-> Text Text) + (format content text.new_line text.new_line)) + +(def: #export (plural singular) + (-> Text Text) + (format singular "(s)")) + +(def: #export (sentence content) + (-> Text Text) + (format content ".")) + +(def: #export paragraph + (-> (List Text) Text) + (|>> (list\map ..sentence) + (text.join_with text.new_line))) + +(template [ ] + [(def: #export + (-> (List Text) Text) + (text.join_with (format ", " " ")))] + + [or "or"] + [and "and"] + [and/or "and/or"] + ) + +(type: #export Section + {#title Text + #content Text}) + +(def: #export (section value) + (-> Section Text) + (format (..block (get@ #title value)) + (get@ #content value))) diff --git a/licentia/source/program/licentia/input.lux b/licentia/source/program/licentia/input.lux new file mode 100644 index 000000000..52205762d --- /dev/null +++ b/licentia/source/program/licentia/input.lux @@ -0,0 +1,167 @@ +(.module: + [lux #* + [abstract + [monad (#+ do)]] + [control + ["." exception (#+ exception:)] + ["<>" parser + ["<.>" json (#+ Parser)]]] + [data + [text + ["%" format (#+ format)]]] + [math + [number + ["n" nat] + ["i" int] + ["f" frac]]]] + ["." // #_ + ["#" license (#+ Identification + Termination + Liability + Distribution + Commercial + Extension + Entity Black_List + URL Attribution + Addendum + License) + ["." time (#+ Period)] + ["." copyright]]]) + +(def: identification + (Parser Identification) + (.object + ($_ <>.and + (.field "name" .string) + (.field "version" .string)))) + +(exception: #export (cannot_use_fractional_amount {amount Frac}) + (exception.report + ["Amount" (%.frac amount)])) + +(exception: #export (cannot_use_negative_amount {amount Int}) + (exception.report + ["Amount" (%.int amount)])) + +(def: amount + (Parser Nat) + (do <>.monad + [amountF .number + #let [amountI (f.int amountF)] + _ (<>.assert (exception.construct ..cannot_use_fractional_amount [amountF]) + (f.= amountF + (i.frac amountI))) + _ (<>.assert (exception.construct ..cannot_use_negative_amount [amountI]) + (i.> +0 amountI))] + (wrap (.nat amountI)))) + +(exception: #export (invalid_period {period (Period Nat)}) + (exception.report + ["Start" (%.nat (get@ #time.start period))] + ["End" (%.nat (get@ #time.end period))])) + +(def: period + (Parser (Period Nat)) + (.object + (do <>.monad + [start (.field "start" ..amount) + end (.field "end" ..amount) + #let [period {#time.start start + #time.end end}] + _ (<>.assert (exception.construct ..invalid_period [period]) + (n.<= end start))] + (wrap period)))) + +(def: copyright_holder + (Parser copyright.Holder) + (.object + ($_ <>.and + (.field "name" .string) + (.field "period" ..period)))) + +(def: termination + (Parser Termination) + (.object + ($_ <>.and + (.field "patent retaliation?" .boolean) + (.field "termination period" ..amount) + (.field "grace period" ..amount)))) + +(def: liability + (Parser Liability) + (.object + ($_ <>.and + (.field "can accept?" .boolean) + (.field "disclaim high risk?" .boolean)))) + +(def: distribution + (Parser Distribution) + (.object + ($_ <>.and + (.field "can re-license?" .boolean) + (.field "can multi-license?" .boolean)))) + +(def: commercial + (Parser Commercial) + (.object + ($_ <>.and + (.field "can sell?" .boolean) + (.field "require contributor credit?" .boolean) + (.field "allow contributor endorsement?" .boolean)))) + +(def: extension + (Parser Extension) + (.object + ($_ <>.and + (.field "same license?" .boolean) + (.field "must be distinguishable?" .boolean) + (.field "notification period" (.nullable ..period)) + (.field "must describe modifications?" .boolean)))) + +(def: entity + (Parser Entity) + .string) + +(def: black_list + (Parser Black_List) + (.object + ($_ <>.and + (.field "justification" (.nullable .string)) + (.field "entities" (.array (<>.many ..entity)))))) + +(def: url + (Parser URL) + .string) + +(def: attribution + (Parser Attribution) + (.object + ($_ <>.and + (.field "copyright-notice" .string) + (.field "phrase" (.nullable .string)) + (.field "url" ..url) + (.field "image" (.nullable ..url))))) + +(def: addendum + (Parser Addendum) + (.object + ($_ <>.and + (.field "commons clause?" .boolean) + ))) + +(def: #export license + (Parser License) + (.object + ($_ <>.and + (.field "copyright-holders" (.array (<>.many ..copyright_holder))) + (.field "identification" (.nullable ..identification)) + (.field "termination" ..termination) + (.field "liability" ..liability) + (.field "distribution" ..distribution) + (.field "commercial" ..commercial) + (.field "extension" ..extension) + (.field "black-lists" (.array (<>.some ..black_list))) + (.field "attribution" (.nullable ..attribution)) + (<>.default {#//.commons_clause? false} + (.field "addendum" ..addendum)) + ))) diff --git a/licentia/source/program/licentia/license.lux b/licentia/source/program/licentia/license.lux new file mode 100644 index 000000000..ad7328641 --- /dev/null +++ b/licentia/source/program/licentia/license.lux @@ -0,0 +1,62 @@ +(.module: + [lux #*] + ["." / #_ + [time (#+ Days Months Period)] + ["#." copyright]]) + +(type: #export Identification + {#name Text + #version Text}) + +(type: #export Termination + {#patent_retaliation? Bit + #termination_period Days + #grace_period Days}) + +(type: #export Liability + {#can_accept? Bit + #disclaim_high_risk? Bit}) + +(type: #export Distribution + {#can_re_license? Bit + #can_multi_license? Bit}) + +(type: #export Commercial + {#can_sell? Bit + #require_contributor_credit? Bit + #allow_contributor_endorsement? Bit}) + +(type: #export Extension + {#same_license? Bit + #must_be_distinguishable? Bit + #notification_period (Maybe (Period Months)) + #must_describe_modifications? Bit}) + +(type: #export Entity Text) + +(type: #export Black_List + {#justification (Maybe Text) + #entities (List Entity)}) + +(type: #export URL Text) + +(type: #export Attribution + {#copyright_notice Text + #phrase (Maybe Text) + #url URL + #image (Maybe URL)}) + +(type: #export Addendum + {#commons_clause? Bit}) + +(type: #export License + {#copyright_holders (List /copyright.Holder) + #identification (Maybe Identification) + #termination Termination + #liability Liability + #distribution Distribution + #commercial Commercial + #extension Extension + #black_lists (List Black_List) + #attribution (Maybe Attribution) + #addendum Addendum}) diff --git a/licentia/source/program/licentia/license/addendum.lux b/licentia/source/program/licentia/license/addendum.lux new file mode 100644 index 000000000..e4a8d6364 --- /dev/null +++ b/licentia/source/program/licentia/license/addendum.lux @@ -0,0 +1,28 @@ +(.module: + [lux #* + [data + [text + ["%" format (#+ format)]]]] + ["." // (#+ Addendum) + [// + ["$" document]]]) + +## https://commonsclause.com/ +(def: #export commons_clause + Text + (format ($.block "The Software is provided to you by the Licensor under the License, as defined below, subject to the following condition.") + ($.block "Without limiting other conditions in the License, the grant of rights under the License will not include, and the License does not grant to you, the right to Sell the Software.") + ($.block "For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you under the License to provide to third parties, for a fee or other consideration (including without limitation fees for hosting or consulting/ support services related to the Software), a product or service whose value derives, entirely or substantially, from the functionality of the Software. Any license notice or attribution required by the License must also include this Commons Clause License Condition notice."))) + +(def: #export (output value) + (-> Addendum Text) + (`` (format (~~ (template [ <condition> <content>] + [(if <condition> + ($.block ($.section {#$.title <title> + #$.content <content>})) + "")] + + ["“Commons Clause” License Condition v1.0" + (get@ #//.commons_clause? value) + ..commons_clause] + ))))) diff --git a/licentia/source/program/licentia/license/assurance.lux b/licentia/source/program/licentia/license/assurance.lux new file mode 100644 index 000000000..5c1adfef7 --- /dev/null +++ b/licentia/source/program/licentia/license/assurance.lux @@ -0,0 +1,25 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + [// + ["_" term] + [// + ["$" document]]]) + +(def: #export representation + ($.sentence (format "Each " _.contributor + " represents that the " _.contributor + " believes its " ($.plural _.contribution) + " are its original creation(s) or it has sufficient rights to grant the rights to its " ($.plural _.contribution) + " conveyed by " _.license))) + +(def: #export fair_use + (let [copyright_doctrines (: (List Text) + (list "fair use" + "fair dealing" + "other equivalents"))] + ($.sentence (format _.license + " is not intended to limit any rights " _.recipient + " has under applicable copyright doctrines of " ($.or copyright_doctrines))))) diff --git a/licentia/source/program/licentia/license/black_list.lux b/licentia/source/program/licentia/license/black_list.lux new file mode 100644 index 000000000..d260f1865 --- /dev/null +++ b/licentia/source/program/licentia/license/black_list.lux @@ -0,0 +1,31 @@ +(.module: + [lux #* + [data + ["." maybe ("#\." functor)] + ["." text + ["%" format (#+ format)]] + [collection + ["." list ("#\." functor)]]]] + ["." // (#+ Entity Black_List) + ["_" term] + [// + ["$" document]]]) + +(def: #export entity + (-> Entity Text) + %.text) + +(def: #export (black_list black_list) + (-> Black_List Text) + (let [scope (format "The rights granted under " _.license) + effect "shall not be granted to the following entities, or any subsidiary thereof" + justification (|> black_list + (get@ #//.justification) + (maybe\map (|>> (format ", due to "))) + (maybe.default "")) + entities (|> black_list + (get@ #//.entities) + (list\map ..entity) + (text.join_with text.new_line))] + (format scope " " effect justification ":" text.new_line + entities))) diff --git a/licentia/source/program/licentia/license/commercial.lux b/licentia/source/program/licentia/license/commercial.lux new file mode 100644 index 000000000..a17acdbb3 --- /dev/null +++ b/licentia/source/program/licentia/license/commercial.lux @@ -0,0 +1,30 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + ["." // (#+ Commercial) + ["_" term] + [// + ["$" document]]]) + +(def: #export cannot_sell + (let [preamble (format "Without limiting other conditions in " _.license) + direct_condition (format "the grant of rights under " _.license + " will not include, and does not grant to " _.recipient + ", the right to " _.sell " " _.work) + derivative_condition (format "or any " _.derivative_work)] + ($.sentence (format preamble + ", " direct_condition + ", " derivative_condition)))) + +(def: #export require_contributor_attribution + ($.sentence (format "All advertising materials mentioning features or use of " _.work + " must include an acknowledgement of the authorship of every " _.contributor))) + +(def: #export disallow_contributor_endorsement + (let [subject (format "The name of no " _.contributor) + capability "endorse or promote products" + source (format "any " _.extension) + condition "specific prior written permission"] + ($.sentence (format subject " may be used to " capability " derived from " source " without " condition)))) diff --git a/licentia/source/program/licentia/license/copyright.lux b/licentia/source/program/licentia/license/copyright.lux new file mode 100644 index 000000000..872af9d2b --- /dev/null +++ b/licentia/source/program/licentia/license/copyright.lux @@ -0,0 +1,8 @@ +(.module: + [lux #*] + [// + [time (#+ Year Period)]]) + +(type: #export Holder + {#name Text + #period (Period Year)}) diff --git a/licentia/source/program/licentia/license/definition.lux b/licentia/source/program/licentia/license/definition.lux new file mode 100644 index 000000000..e93230b33 --- /dev/null +++ b/licentia/source/program/licentia/license/definition.lux @@ -0,0 +1,240 @@ +(.module: + [lux (#- Definition) + [data + ["." text + ["%" format (#+ format)]]]] + [/// + ["$" document]]) + +(type: #export Definition + {#term Text + #meaning Text}) + +(def: not_a_contribution_notice + (format text.double_quote "Not a Contribution" text.double_quote)) + +(def: #export patent_rights + (List Text) + (list "make" + "have made" + "use" + "offer to sell" + "sell" + "import" + "transfer")) + +(def: commercial_services + (List Text) + (let [services (: (-> Text Text) + (function (_ type) + (format type " services")))] + (list (services "hosting") + (services "consulting") + (services "support")))) + +(def: individual_capacities + (List Text) + (list "officer" + "employee" + "member" + "independent contractor" + "agent of a corporation, business or organization (commercial or non-commercial)")) + +(def: covered_work_description + "work of authorship") + +(template [<name> <term> <meaning>] + [(def: #export <name> + Definition + {#term <term> + #meaning <meaning>})] + + [license "This License" + ($.paragraph (list (format "the terms and conditions defined in this document")))] + + [licensable "Licensable" + ($.paragraph (list (format "having the right to grant any and all of the rights conveyed by " (get@ #term license))))] + + [legal_entity "Legal Entity" + (let [abilities (: (List Text) + (list "to enter into contracts" + "to sue" + "to be sued"))] + ($.paragraph (list (format "any human or non-human entity that is recognized as having privileges and obligations, such as having the ability " ($.and abilities)))))] + + [recipient "Recipient" + ($.paragraph (list (format "a " (get@ #term legal_entity) " exercising permissions by " (get@ #term license))))] + + [licensor "The Licensor" + ($.paragraph (list (format "the copyright owner granting " (get@ #term license) ", or a " (get@ #term legal_entity) " authorized by the copyright owner")))] + + [source_code_form "Source Code Form" + ($.paragraph (list (format "the preferred form of the " ..covered_work_description " in order to make modifications to it")))] + + [object_form "Object Form" + ($.paragraph (list (format "any form produced by transforming a " (get@ #term source_code_form) ", including but not limited to compiled code and transpiled code")))] + + [work "The Work" + ($.paragraph (list (format "the " ..covered_work_description + ", whether in a " (get@ #term source_code_form) + " or in an " (get@ #term object_form) + ", made available under " (get@ #term license) + ", as indicated by a copyright notice that is included in or attached to the " ..covered_work_description)))] + + [derivative_work "Derivative Work" + ($.paragraph (list (format "any work, whether in a " (get@ #term source_code_form) + " or in an " (get@ #term object_form) + ", that is based on (or derived from) " (get@ #term work) + " and which represents an original " ..covered_work_description)))] + + [submission "Submission" + (let [forms_of_communication (: (List Text) + (list "electronic" + "verbal" + "written"))] + ($.paragraph (list (format "any form of " ($.or forms_of_communication) " communication sent to " (get@ #term licensor) + ", or its representatives, for the purpose of discussing and improving " (get@ #term work) + ", but excluding communication that is designated in writing by the copyright owner as " not_a_contribution_notice))))] + + [modification "Modification" + (let [alteration "any addition to, or deletion from, the substance or structure of" + object "file or other storage" + targets (: (List Text) + (list (format "a " object " contained in " (get@ #term work)) + (format "any new " object " that contains any part of " (get@ #term work)) + (format "any " object " which replaces or otherwise alters the original functionality of "(get@ #term work) " at runtime")))] + ($.paragraph (list (format alteration " " ($.or targets)))))] + + [required_component "Required Component" + (let [possibilities (: (List Text) + (list "text" + "program" + "script" + "schema" + "interface definition" + "control file" + "other work"))] + ($.paragraph (list (format "any " ($.or possibilities) + " created by " (get@ #term recipient) + " which is required by a third party to successfully install and run a " (get@ #term derivative_work) + " by " (get@ #term recipient)))))] + + [extension "Extension" + (let [possibilities (: (List Text) + (list (get@ #term modification) + (get@ #term derivative_work) + (get@ #term required_component)))] + ($.paragraph (list (format "any " ($.or possibilities)))))] + + [contribution "Contribution" + ($.paragraph (list (format "any " covered_work_description ", including the original version of " (get@ #term work) + " and any " (get@ #term extension) " to " (get@ #term work) + ", that is intentionally communicated as a " (get@ #term submission) + " to " (get@ #term licensor) + " for inclusion in " (get@ #term work) " by the copyright owner" + ", or by a " (get@ #term legal_entity) " authorized to submit on behalf of the copyright owner")))] + + [contributor "Contributor" + ($.paragraph (list (format (get@ #term licensor) + " or any " (get@ #term legal_entity) + " on behalf of whom a " (get@ #term contribution) + " has been received by " (get@ #term licensor) + ", and subsequently incorporated within " (get@ #term work))))] + + [patent_claim (format "Patent Claim Of A " (get@ #term contributor)) + (let [claim_types (: (List Text) + (list "method" + "process" + "apparatus"))] + ($.paragraph (list (format "any patent claim(s), including without limitation " ($.and claim_types) " claims, in any patent " + (get@ #term licensable) " by such " (get@ #term contributor) + " that would be infringed, but for the grant of " (get@ #term license) + ", to " ($.or patent_rights) " its " (get@ #term contribution)))))] + + [secondary_license "Secondary License" + ($.paragraph (list (format "any license for which compliance does not imply or require violating the terms of " (get@ #term license))))] + + [sell "Sell" + ($.paragraph (list (format "practicing any or all of the rights granted to " (get@ #term recipient) + " under " (get@ #term license) + " to provide to third parties, for a fee or other consideration " + "(including without limitation fees for " ($.or commercial_services) + " related to "(get@ #term work) ")" + ", a product or service whose value derives, entirely or substantially, from the functionality of " (get@ #term work))))] + + [personal_use "Personal Use" + (let [valid_purposes (: (List Text) + (list "personal" + "private" + "non-commercial"))] + ($.paragraph (list (format "use of " (get@ #term work) " by an individual solely for his or her " ($.and valid_purposes) " purposes") + (format "An individual's use of " (get@ #term work) " in his or her capacity as an " ($.or individual_capacities) " does not qualify"))))] + + [serve "Serve" + ($.paragraph (list (format "to deliver " (get@ #term work) + " and/or any " (get@ #term extension) + " by means of a computer network to one or more computers for purposes of execution of " (get@ #term work) + ", and/or the " (get@ #term extension))))] + + [research "Research" + ($.paragraph (list (format "investigation or experimentation for the purpose of understanding the nature and limits of " (get@ #term work) " and its potential uses")))] + + [deploy "Deploy" + (let [deployment_types (: (List Text) + (list "use" + (get@ #term serve) + "sublicense" + "distribute")) + sub_licensing (: (-> Text Text) + (function (_ type) + (format type " sublicensing"))) + third_party_interactions (: (List Text) + (list (sub_licensing "direct") + (sub_licensing "indirect") + "distribution")) + basic_definition (format "to " ($.or deployment_types) + " " (get@ #term work) + " other than for internal " (get@ #term research) + " and/or " (get@ #term personal_use) + " by " (get@ #term recipient)) + examples (format "any and all internal use or distribution of " (get@ #term work) + " within a business or organization in which " (get@ #term recipient) + " participates") + exceptions (format "for " (get@ #term research) " and/or " (get@ #term personal_use))] + ($.paragraph (list (format basic_definition + ", and includes without limitation, " examples + ", other than " exceptions + ", as well as " ($.or third_party_interactions) + " of " (get@ #term work) + " by " (get@ #term recipient) + " to any third party in any form or manner"))))] + + [electronic_distribution_mechanism "Electronic Distribution Mechanism" + ($.paragraph (list "a mechanism generally accepted in the software development community for the electronic transfer of data, such as download from an FTP server or web site, where such mechanism is publicly accessible"))] + ) + +(def: #export all + (List Definition) + (list license + licensable + legal_entity + recipient + licensor + source_code_form + object_form + work + derivative_work + submission + modification + required_component + extension + contribution + contributor + patent_claim + secondary_license + sell + personal_use + serve + research + deploy + electronic_distribution_mechanism)) diff --git a/licentia/source/program/licentia/license/distribution.lux b/licentia/source/program/licentia/license/distribution.lux new file mode 100644 index 000000000..8ec4e9bae --- /dev/null +++ b/licentia/source/program/licentia/license/distribution.lux @@ -0,0 +1,112 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]] + [collection + ["." list ("#\." monoid)]]]] + ["." // (#+ Distribution) + ["_" term] + [// + ["$" document]]]) + +(def: notices + (List Text) + (let [notices (: (-> Text Text) + (function (_ what) + (format what " notices")))] + (list (notices "copyright") + (notices "patent") + (notices "trademark") + (notices "attribution") + (notices "disclaimer of warranty") + (notices "limitation of liability") + (notices "other")))) + +(def: #export source_code_form + (let [on_license_propagation (let [coverage (format "All distribution of " _.work " in " _.source_code_form) + with_contributions (format "including any " ($.plural _.contribution) + " that " _.recipient + " creates") + same_license (format "must be under the terms of " _.license)] + (format coverage ", " with_contributions ", " same_license)) + on_license_access (let [responsibility_to_inform (format _.recipient + " must inform recipients that the " _.source_code_form + " of " _.work + " is governed by the terms of " _.license) + license_copy (format "and how they can obtain a copy of " _.license)] + (format responsibility_to_inform ", " license_copy)) + on_license_immutability (format _.recipient + " may not attempt to alter or restrict the recipients’ rights in the " _.source_code_form + ", as specified in " _.license) + on_notice_retention (let [obligation (format _.recipient " must retain") + location (format "in the " _.source_code_form + " of any " _.extension + " that " _.recipient + " distributes") + what (format "all " ($.and notices) " from the " _.source_code_form " of " _.work) + exclusion ($.or (list (format "those notices that do not pertain to any part of the " _.extension) + "those notices that contain known factual inaccuracies"))] + (format obligation ", " location ", " what ", excluding " exclusion)) + on_additional_notices (let [right (format _.recipient + " may add additional "($.and notices) + " within an " _.extension + " that " _.recipient + " distributes") + constraint (format "such additional " ($.and notices) " cannot be construed as modifying " _.license)] + (format right ", provided that " constraint))] + ($.paragraph (list on_license_propagation + on_license_access + on_license_immutability + on_notice_retention + on_additional_notices)))) + +(def: #export object_form + (let [on_responsibility (let [condition (format "If " _.recipient + " distributes " _.work + " in " _.object_form) + responsibility (let [availability_responsibility (format _.work " must also be made available in " _.source_code_form) + source_code_responsibility (format _.recipient + " must inform recipients of the " _.object_form + " how they can obtain a copy of such " _.source_code_form) + constraints "by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient"] + (format availability_responsibility ", and " source_code_responsibility " " constraints))] + (format condition " then " responsibility)) + on_licensing (format _.recipient + " may distribute such " _.object_form + " under the terms of "_.license)] + ($.paragraph (list on_responsibility + on_licensing)))) + +(def: #export allow_re_licensing + (let [can_license (format _.recipient + " may create and distribute an " _.extension + " under terms " _.recipient + " chooses") + requirement (format _.recipient + " also comply with the requirements of " _.license + " for the " _.work)] + (format can_license ", " "provided that " requirement))) + +(def: #export allow_multi_licensing + (let [condition (format "the " _.extension " is a combination of " _.work " with a work governed by one or more " ($.plural _.secondary_license)) + permission (let [relicensing (format _.license + " permits " _.recipient + " to additionally distribute " _.work + " under the terms of such " ($.plural _.secondary_license)) + distribution (format "so that the recipient of the " _.extension + " may, at their option, further distribute " _.work + " under the terms of either " _.license + " or such " ($.plural _.secondary_license))] + (format relicensing ", " distribution))] + (format "If " condition ", " permission))) + +(def: #export (extension distribution) + (-> Distribution Text) + ($.paragraph ($_ list\compose + (if (get@ #//.can_re_license? distribution) + (list allow_re_licensing) + (list)) + (if (get@ #//.can_multi_license? distribution) + (list allow_multi_licensing) + (list))))) diff --git a/licentia/source/program/licentia/license/extension.lux b/licentia/source/program/licentia/license/extension.lux new file mode 100644 index 000000000..c6b368d33 --- /dev/null +++ b/licentia/source/program/licentia/license/extension.lux @@ -0,0 +1,166 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + ["." // (#+ Extension) + ["_" term] + ["." grant] + [time (#+ Months Period)] + [// + ["$" document]]]) + +(def: #export sharing_requirement + (List Text) + (let [on_extension (let [constraint (let [because "In consideration of, and as an express condition to, " + source (format "the licenses granted to " _.recipient + " under " _.license)] + (format because " " source)) + duty (format _.recipient + " hereby agrees that any " _.extension + " that " _.recipient + " creates or to which " _.recipient + " contributes are governed by the terms of " _.license)] + (format constraint ", " duty)) + on_deployment (format _.recipient " may only " _.deploy + " an " _.extension + " that " _.recipient + " creates under the terms of " _.license) + on_sharing (format _.recipient + " hereby grant to " _.licensor + " and all third parties a " ($.and grant.grant_characteristics) + " license under those intellectual property rights " _.recipient + " owns or controls to " ($.or grant.copyright_grant_rights) + " " _.work + " in any form") + on_license_propagation (format _.recipient + " must include a copy of " _.license + " or directions on how to obtain a copy with every copy of an " _.extension + " " _.recipient " distributes") + on_license_protection (format _.recipient + " agrees not to offer or impose any terms on any " _.source_code_form + " or " _.object_form + " of the " _.work + ", or its " _.extension + " that alter or restrict the applicable version of " _.license + " or the recipients' rights hereunder")] + (list on_extension + on_deployment + on_sharing + on_license_propagation + on_license_protection))) + +(def: #export license_conflict_resolution + (List Text) + (let [on_other_licenses (let [circumstance (format "Where any portion of an " _.extension + " created by " _.recipient) + consequence "fall under the terms of another license" + duty "the terms of that license should be honored"] + (format circumstance " " consequence ", " duty)) + on_this_license (format "However " _.recipient + " must also make the " _.extension + " available under " _.license) + on_licensor_judgement (let [condition (format "the terms of " _.license " continue to conflict with the terms of the other license") + right (format _.recipient " may write " _.licensor " for permission to resolve the conflict") + characteristic (format "a fashion that remains consistent with the intent of " _.license)] + (format "If " condition ", " right " in " characteristic)) + on_licensor_discretion (format "Such permission will be granted at the sole discretion of " _.licensor)] + (list on_other_licenses + on_this_license + on_licensor_judgement + on_licensor_discretion))) + +(def: #export distinctness_requirement + ($.paragraph (list (format "Any " _.extension + " " _.recipient + " does make and " _.deploy + " must have a distinct title so as to readily tell any subsequent user or " _.contributor + " that the " _.extension + " is by " _.recipient)))) + +(def: news_sources + (List Text) + (list "news groups" + "mailing lists" + "weblogs" + "other sites")) + +(def: #export (notification_requirement [start end]) + (-> (Period Months) Text) + (let [on_availability (format _.recipient + " must notify the software community of the availability of the " _.source_code_form + " to any " _.extension + " created by " _.recipient + " within " (%.nat start) + " month(s) of the date " _.recipient + " initially does " _.deploy + ", and include in such notification a description of the " _.extension + ", and instructions on how to acquire the " _.source_code_form + " via an " _.electronic_distribution_mechanism) + on_duration (format "The " _.source_code_form + " must remain available via an " _.electronic_distribution_mechanism + " for no less than " (%.nat end) + " month(s) after the date " _.recipient + " ceases to " _.deploy) + on_responsibility (format _.recipient + " is responsible for ensuring that the " _.source_code_form + " to each " _.extension + " " _.recipient + " does " _.deploy + " remains available even if the " _.electronic_distribution_mechanism + " is maintained by a third party") + on_costs (format _.recipient + " may not charge a fee for any copy of the " _.source_code_form + " in excess of the actual cost of duplication and distribution of said copy that " _.recipient + " incurs") + on_changes (format "Should such instructions change, " _.recipient + " must notify the software community of revised instructions within " (%.nat start) + " month(s) of the date of change") + on_accesibility (format _.recipient + " must provide notification by posting to appropriate " ($.or news_sources) + " where a publicly accessible search engine would reasonably be expected to index a post in relationship to queries regarding " _.work + " and/or an " _.extension + " created by " _.recipient)] + ($.paragraph (list on_availability + on_duration + on_responsibility + on_costs + on_changes + on_accesibility)))) + +(def: #export description_requirement + Text + (let [on_duty (let [basic (format _.recipient + " must cause any " _.modification + " that " _.recipient + " creates, or to which " _.recipient + " contributes, to be documented in the " _.source_code_form) + modification_types (: (List Text) + (list "additions" + "changes" + "deletions")) + details (format "clearly describing the " ($.and modification_types) + " that " _.recipient " made")] + (format basic ", " details)) + on_notice_location (let [statement_locations (: (List Text) + (list (format "in the " _.source_code_form) + (format "in any notice displayed by " _.work + " " _.recipient + " distributes") + (format "in related documentation in which " _.recipient + " describes the origin or ownership of " _.work)))] + (format _.recipient + " must include a prominent statement that the " _.modification + " is derived, directly or indirectly, from " _.work + " and include the names of " _.licensor + " and any " _.contributor + " to " _.work + " " ($.and statement_locations))) + on_notice_preservation (format _.recipient + " may not modify or delete any pre-existing copyright notices, change notices or the text of " _.license + " in " _.work + " without written permission of " _.licensor + " or the respective " _.contributor)] + ($.paragraph (list on_duty + on_notice_location + on_notice_preservation)))) diff --git a/licentia/source/program/licentia/license/grant.lux b/licentia/source/program/licentia/license/grant.lux new file mode 100644 index 000000000..c79fcee09 --- /dev/null +++ b/licentia/source/program/licentia/license/grant.lux @@ -0,0 +1,128 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + [// + [time (#+ Days)] + ["_" term] + ["." definition] + [// + ["$" document]]]) + +(def: grant_header + (format "Subject to the terms and conditions of " _.license + ", each " _.contributor + " hereby grants to " _.recipient)) + +(def: #export grant_characteristics + (List Text) + (list "perpetual" + "world-wide" + "non-exclusive" + "no-charge" + "royalty-free" + "irrevocable")) + +(def: #export copyright_grant_rights + (List Text) + (list "use" + "reproduce" + "display" + "perform" + "modify" + (format "create an " _.extension " of") + "sublicense" + "distribute")) + +(def: #export copyright + ($.sentence (format grant_header " a " ($.and ..grant_characteristics) + " copyright license to " ($.or ..copyright_grant_rights) + " " _.work + " and such an " _.extension + " in a " _.source_code_form + " or an " _.object_form))) + +(def: #export (patent retaliation?) + (-> Bit Text) + (let [grant (format grant_header " a " ($.and ..grant_characteristics) + " patent license to " ($.or definition.patent_rights) " " + _.work + ", where such license applies only to any " _.patent_claim + " that is necessarily infringed by their " ($.plural _.contribution) + " alone or by combination of their " ($.plural _.contribution) + " with " _.work) + retaliation_clause (format "If " _.recipient " institutes patent litigation against any " _.legal_entity + " (including a cross-claim or counterclaim in a lawsuit) alleging that " + _.work " or a " _.contribution + " incorporated within " _.work " constitutes direct or contributory patent infringement" + ", then any patent licenses granted to " _.recipient + " under " _.license + " for " _.work + " shall terminate as of the date such litigation is filed")] + ($.paragraph (list& grant + (if retaliation? + (list retaliation_clause) + (list)))))) + +(def: #export date + ($.sentence (format "The licenses granted in " _.license + " with respect to any " _.contribution + " become effective for each " _.contribution + " on the date the " _.contributor + " first distributes such " _.contribution))) + +(def: restoration_scope "an ongoing basis") + +(def: #export (grant_restoration_clause termination_period) + (-> Days Text) + (let [restoration_condition (format _.recipient " becomes compliant") + restored_grants (format "the rights granted under " _.license + " from a particular " _.contributor) + invalidation_condition (format "such " _.contributor + " explicitly and finally terminates the grants to " _.recipient) + complaint_period_condition (format "such " _.contributor + " fails to notify " _.recipient + " of the non-compliance by some reasonable means prior to " (%.nat termination_period) + " " ($.plural "day") " after " _.recipient + " has come back into compliance")] + (format "However, if " restoration_condition ", then " restored_grants " are reinstated provisionally" + ", unless and until " invalidation_condition + ", and on " ..restoration_scope ", if " complaint_period_condition))) + +(def: #export (grace_period_clause grace_period) + (-> Days Text) + (let [the_grants (format "grants to " _.recipient " from a particular " _.contributor) + automatic_restoration_conditions (let [notification (format "such " _.contributor + " notifies " _.recipient + " of the non-compliance by some reasonable means") + first_offense (format "this is the first time " _.recipient + " has received notice of non-compliance with " _.license + " from such " _.contributor) + prompt_compliance (format _.recipient + " becomes compliant prior to " (%.nat grace_period) + " " ($.plural "day") " after reception of the notice")] + ($.and (list notification + first_offense + prompt_compliance)))] + (format "Moreover, " the_grants + " are reinstated on " ..restoration_scope + " if " automatic_restoration_conditions))) + +(def: #export (termination termination_period grace_period) + (-> Days Days Text) + (let [on_violation_of_terms (let [what (format "The rights granted under " _.license) + when (format _.recipient " fails to comply with any of its terms")] + (format what " will terminate automatically if " when))] + ($.paragraph (list on_violation_of_terms + (..grant_restoration_clause termination_period) + (..grace_period_clause grace_period))))) + +(def: #export no_retroactive_termination + (let [situation "In the event of termination" + coverage "all end user license agreements" + exclusions "(excluding licenses to distributors and resellers)" + source (format "that have been validly granted by " _.recipient " or any distributor") + scope "hereunder prior to termination" + effect "shall survive termination"] + ($.paragraph (list (format situation ", " coverage " " exclusions " " source " " scope " " effect))))) diff --git a/licentia/source/program/licentia/license/liability.lux b/licentia/source/program/licentia/license/liability.lux new file mode 100644 index 000000000..1ad88c43d --- /dev/null +++ b/licentia/source/program/licentia/license/liability.lux @@ -0,0 +1,160 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + [// + ["_" term] + [// + ["$" document]]]) + +(def: warranty_communications + (List Text) + (list "expressed" + "implied" + "statutory")) + +(def: work_disclamers + (List Text) + (list "free of defects" + "merchantable" + "fit for a particular purpose" + "non-infringing")) + +(def: fixes + (List Text) + (list "servicing" + "repair" + "correction")) + +(def: #export warranty + (let [on_basics (let [applicability_escape "Unless required by applicable law or agreed to in writing" + work_provisioning (format _.licensor + " provides " _.work + ", and each " _.contributor + " provides its " ($.plural _.contribution))] + (format applicability_escape ", " + work_provisioning + " under " _.license + " on an " ($.quote "as is") + " basis, without warranty or condition of any kind, either " ($.or warranty_communications) + " including, without limitation, any warranties or conditions that " _.work + " is " ($.or work_disclamers))) + on_distribution (format _.recipient + " is solely responsible for determining the appropriateness of using or redistributing " _.work) + on_risk (format "The entire risk as to the quality and performance of " _.work + " is with " _.recipient) + on_fixes (format "Should " _.work + " prove defective in any respect, " _.recipient + ", not any " _.contributor + ", assumes the cost of any necessary " ($.or fixes)) + on_importance (format "This disclaimer of warranty constitutes an essential part of "_.license) + on_authorization (format "No use of "_.work + " is authorized under " _.license + " except under this disclaimer")] + ($.paragraph (list on_basics + on_distribution + on_risk + on_fixes + on_importance + on_authorization)))) + +(def: damage_types + (List Text) + (list "direct" + "indirect" + "special" + "incidental" + "consequential")) + +(def: damage_consequences + (List Text) + (list "lost profits" + "loss of goodwill" + "work stoppage" + "computer failure or malfunction" + "any and all other commercial damages or losses")) + +(def: #export limitation + (let [on_limit (let [exclusion "Under no circumstances and under no legal theory" + examples "whether tort (including negligence), contract, or otherwise" + applicable_law_exception "unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing" + renunciation (format "shall any " _.contributor + " be liable to " _.recipient) + damage_enumeration (format "for any " ($.or damage_types) " damages of any character" + " including without limitation damages for " ($.or damage_consequences)) + conscience "even if such party shall have been informed of the possibility of such damages"] + (format exclusion ", " examples ", " applicable_law_exception ", " renunciation " " damage_enumeration ", " conscience)) + on_death_exception "This limitation of liability shall not apply to liability for death or personal injury resulting from such party’s negligence to the extent applicable law prohibits such limitation" + on_jurisdictions (format "Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to " _.recipient)] + ($.paragraph (list on_limit + on_death_exception + on_jurisdictions)))) + +(def: #export litigation + (let [on_jurisdiction (format "Any litigation relating to " _.license " may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business") + on_laws "Such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions" + on_claims "Nothing in this section shall prevent a party’s ability to bring cross-claims or counter-claims"] + ($.paragraph (list on_jurisdiction + on_laws + on_claims)))) + +(def: liability_obligations + (List Text) + (list "support" + "warranty" + "indemnity" + "other liability obligations" + (format "rights consistent with " _.license))) + +(def: #export can_accept + (let [on_acceptance_of_liability (let [condition (format "While redistributing " _.work " or " ($.plural _.extension) " thereof") + right (format _.recipient " may choose to offer, and charge a fee for, acceptance of " ($.and/or ..liability_obligations))] + (format condition ", " right)) + on_responsibility (let [but "However, in accepting such obligations" + cannot_represent_a_contributor (format _.recipient " may not act on behalf of any other " _.contributor) + can_only_represent_oneself (format "only on behalf and on sole responsibility of " _.recipient) + each_contributor (: (-> Text Text) + (function (_ responsibility) + (format responsibility " each " _.contributor))) + responsibilities (: (List Text) + (list (each_contributor "indemnify") + (each_contributor "defend") + (format (each_contributor "hold") " harmless"))) + full_responsibility_condition (format "and only if " _.recipient + " agrees to " ($.and responsibilities) + " for any liability incurred by, or claims asserted against, such " _.contributor + " by reason of acceptance of any such warranty or additional liability by " _.recipient)] + (format but ", " cannot_represent_a_contributor ", " can_only_represent_oneself ", " full_responsibility_condition))] + ($.paragraph (list on_acceptance_of_liability + on_responsibility)))) + +(def: #export disclaim_high_risk + (let [on_work (let [intentions (: (List Text) + (list "designed" + "manufactured" + "intended for use or distribution")) + hazardous_environments (: (List Text) + (list "nuclear facilities" + "aircraft navigation" + "communications systems" + "air traffic control" + "direct life support machines" + "weapons systems")) + consequences (: (List Text) + (list "death" + "personal injury" + "severe physical damage" + "environmental damage")) + disclaim (format _.work " is not fault tolerant" + ", and is not " ($.or intentions) + " as on-line control equipment in hazardous environments requiring fail-safe performance") + examples (format "such as in the operation of " ($.or hazardous_environments)) + further (format "in which the failure of " _.work " could lead directly to " ($.or consequences))] + (format disclaim ", " examples ", " further)) + on_contributors (let [claim "any express or implied warranty of fitness for high risk activities"] + (format _.licensor + " and every " _.contributor + " specifically disclaim " claim))] + ($.paragraph (list on_work + on_contributors)))) diff --git a/licentia/source/program/licentia/license/limitation.lux b/licentia/source/program/licentia/license/limitation.lux new file mode 100644 index 000000000..046e60a55 --- /dev/null +++ b/licentia/source/program/licentia/license/limitation.lux @@ -0,0 +1,75 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + [// + ["_" term] + [// + ["$" document]]]) + +(def: #export acceptance + (let [abilities (: (List Text) + (list "use" + "copy" + "distribute" + "modify" + (format "create an " _.extension + " of either " _.work + " or any " _.extension + " created by a " _.contributor))) + acknowledgement (format _.recipient + " is not required to accept " _.license + " since " _.recipient + " has not signed it") + limitation (format "However, nothing else grants " _.recipient + " permission to " ($.or abilities)) + warning (format "These actions are prohibited by law if " _.recipient + " does not accept " _.license) + implicit_acceptance (let [activation_condition "by performing any of these actions" + acceptance (format _.recipient + " indicates that " _.recipient + " accepts " _.license) + agreement (format _.recipient " agrees to be bound by all its terms and conditions")] + (format "Therefore, " activation_condition ", " ($.and (list acceptance agreement)))) + prohibition_due_to_non_agreement (format "If " _.recipient + " does not agree with all the terms and conditions of " _.license + ", " _.recipient " can not " ($.or abilities)) + prohibition_due_to_impossibility (format "If it is impossible for " _.recipient + " to comply with all the terms and conditions of " _.license + ", then " _.recipient + " can not " ($.or abilities))] + ($.paragraph (list acknowledgement + limitation + warning + implicit_acceptance + prohibition_due_to_non_agreement + prohibition_due_to_impossibility)))) + +(def: #export grant + ($.paragraph (list (format "The licenses granted in this document are the only rights granted under " _.license) + (format "No additional rights or licenses will be implied from the distribution or licensing of " _.work + " under " _.license) + (format "No patent license is granted by a " _.contributor + " for any code that the " _.contributor + " has removed from " _.work)))) + +(def: identifiers + (List Text) + (list "trade names" + "trademarks" + "service marks" + "product names" + "logos")) + +(def: #export trademark + ($.paragraph (list (format _.license " does not grant any permission to use the " ($.or ..identifiers) + " of any " _.contributor + "; except as required for reasonable and customary use in describing the origin of " + _.work)))) + +(def: #export secondary_licenses + ($.paragraph (list (format "No " _.contributor + " makes additional grants as a result of a choice by " _.recipient + " to distribute " _.work + " under a under the terms of a " _.secondary_license)))) diff --git a/licentia/source/program/licentia/license/miscellaneous.lux b/licentia/source/program/licentia/license/miscellaneous.lux new file mode 100644 index 000000000..0fbc96982 --- /dev/null +++ b/licentia/source/program/licentia/license/miscellaneous.lux @@ -0,0 +1,106 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + [// + ["_" term] + [// + ["$" document]]]) + +(def: #export entire_agreement + ($.paragraph (list (format _.license " constitutes the entire agreement between the parties with respect to the subject matter hereof")))) + +(def: #export relationship_of_parties + (let [legal_associations (: (List Text) + (list "an agency" + "a partnership" + "a joint venture" + "any other form of legal association")) + forms_of_representation (: (List Text) + (list "expressly" + "by implication" + "by appearance" + "otherwise")) + disclaimer (format _.license " will not be construed as creating " ($.or legal_associations)) + scope (format "between or among " _.recipient + ", " _.licensor + " or any " _.contributor) + constraint (format _.recipient + " will not represent to the contrary, whether " ($.or forms_of_representation))] + ($.paragraph (list (format disclaimer " " scope ", and " constraint))))) + +(def: #export independent_development + (let [actions (: (List Text) + (list "acquire" + "license" + "develop" + "subcontract" + "market" + "distribute" + "produce")) + scope (format "Nothing in " _.license) + effect (format "impair the right of " _.licensor) + target "technology or products" + compete "perform the same or similar functions as, or otherwise compete with," + competition (format "any " _.extension)] + ($.paragraph (list (format scope + " will " effect + " to " ($.or actions) + " " target + " that " compete + " " competition + " that " _.recipient + " may " ($.or actions)))))) + +(def: #export not_waiver + (let [culprits (format _.licensor " or any " _.contributor) + duty (format "enforce any provision of " _.license) + effect "a waiver of future enforcement of that or any other provision"] + ($.paragraph (list (format "Failure by " culprits + " to " duty + " will not be deemed " effect))))) + +(def: #export severability + (let [on_reformation (format "If any provision of " _.license " is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable") + on_contributor_protection (format "Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe " _.license + " against a " _.contributor)] + ($.paragraph (list on_reformation + on_contributor_protection)))) + +(def: #export export_restrictions + (let [limiter "applicable laws and regulations" + limited (: (List Text) + (list "downloading" + "acquiring" + "exporting" + "reexporting")) + on_circumstances (let [limitation (format _.recipient + " may be restricted with respect to " ($.or limited)) + target (format _.work " or any underlying information or technology")] + (format limitation " " target " by " limiter)) + on_acceptance_of_responsibility (let [trigger (format "By " ($.or limited) " " _.work) + agreement (format _.recipient + " is agreeing to be responsible for compliance with all " limiter)] + (format trigger ", " agreement))] + ($.paragraph (list on_circumstances + on_acceptance_of_responsibility)))) + +(def: #export new_versions + (let [on_publishing (let [when ", from time to time," + what (format "revised versions of " _.license)] + (format _.licensor " may publish" when " " what)) + on_published_version_validity (let [condition (format _.work " has been published under a particular version of " _.license) + effect (format _.recipient " may always continue to use it under the terms of that version")] + (format "Once " condition ", " effect)) + on_license_upgrading (format _.recipient + " may also choose to use " _.work + " under the terms of any subsequent version of " _.license + " published by " _.licensor) + on_licensor_privilege (format "No one other than " _.licensor + " has the right to modify the terms applicable to " _.work + " created under " _.license)] + ($.paragraph (list on_publishing + on_published_version_validity + on_license_upgrading + on_licensor_privilege)))) diff --git a/licentia/source/program/licentia/license/notice.lux b/licentia/source/program/licentia/license/notice.lux new file mode 100644 index 000000000..7ee61397a --- /dev/null +++ b/licentia/source/program/licentia/license/notice.lux @@ -0,0 +1,33 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]] + [collection + ["." list ("#\." functor)]]] + [math + [number + ["n" nat]]]] + ["." // #_ + ["#." time] + ["#." copyright] + ["_" term] + [// + ["$" document]]]) + +(def: #export end_of_license + ($.sentence "END OF TERMS AND CONDITIONS")) + +(def: #export (copyright_holder holder) + (-> //copyright.Holder Text) + (let [(^slots [#//time.start #//time.end]) (get@ #//copyright.period holder) + single_year? (n.= start end) + period_section (if single_year? + (%.nat start) + (format (%.nat start) "-" (%.nat end)))] + (format "Copyright (C) " period_section " " (get@ #//copyright.name holder)))) + +(def: #export copyright + (-> (List //copyright.Holder) Text) + (|>> (list\map ..copyright_holder) + (text.join_with text.new_line))) diff --git a/licentia/source/program/licentia/license/submission.lux b/licentia/source/program/licentia/license/submission.lux new file mode 100644 index 000000000..855141690 --- /dev/null +++ b/licentia/source/program/licentia/license/submission.lux @@ -0,0 +1,26 @@ +(.module: + [lux #* + [data + ["." text + ["%" format (#+ format)]]]] + [// + ["_" term] + [// + ["$" document]]]) + +(def: #export contribution + (let [on-submissions (let [exception (format "Unless " _.recipient " explicitly states otherwise") + general-case (format "any intentional " _.submission " of a " _.contribution + " for inclusion in " _.work + " by " _.recipient + " to " _.licensor + " shall be under the terms and conditions of " _.license) + guard "without any additional terms or conditions"] + (format exception ", " general-case ", " guard)) + on-special-cases (let [connection "Notwithstanding the above" + prioritization (format "nothing herein shall supersede or modify the terms of any separate license agreement " _.recipient + " may have executed with " _.licensor + " regarding such " _.contribution)] + (format connection ", " prioritization))] + ($.paragraph (list on-submissions + on-special-cases)))) diff --git a/licentia/source/program/licentia/license/term.lux b/licentia/source/program/licentia/license/term.lux new file mode 100644 index 000000000..c9db7fa5a --- /dev/null +++ b/licentia/source/program/licentia/license/term.lux @@ -0,0 +1,34 @@ +(.module: + [lux (#- Definition)] + ["." // #_ + ["#." definition]]) + +(template [<term> <definition>] + [(def: #export <term> + Text + (get@ #//definition.term <definition>))] + + [source_code_form //definition.source_code_form] + [object_form //definition.object_form] + [license //definition.license] + [licensable //definition.licensable] + [legal_entity //definition.legal_entity] + [recipient //definition.recipient] + [licensor //definition.licensor] + [work //definition.work] + [derivative_work //definition.derivative_work] + [submission //definition.submission] + [modification //definition.modification] + [required_component //definition.required_component] + [extension //definition.extension] + [contribution //definition.contribution] + [contributor //definition.contributor] + [patent_claim //definition.patent_claim] + [secondary_license //definition.secondary_license] + [sell //definition.sell] + [personal_use //definition.personal_use] + [serve //definition.serve] + [research //definition.research] + [deploy //definition.deploy] + [electronic_distribution_mechanism //definition.electronic_distribution_mechanism] + ) diff --git a/licentia/source/program/licentia/license/time.lux b/licentia/source/program/licentia/license/time.lux new file mode 100644 index 000000000..22f28f607 --- /dev/null +++ b/licentia/source/program/licentia/license/time.lux @@ -0,0 +1,15 @@ +(.module: + [lux #*]) + +(type: #export Days + Nat) + +(type: #export Months + Nat) + +(type: #export Year + Nat) + +(type: #export (Period a) + {#start a + #end a}) diff --git a/licentia/source/program/licentia/output.lux b/licentia/source/program/licentia/output.lux new file mode 100644 index 000000000..691612b6e --- /dev/null +++ b/licentia/source/program/licentia/output.lux @@ -0,0 +1,309 @@ +(.module: + [lux (#- Definition) + [data + ["." maybe ("#\." functor)] + ["." text + ["%" format (#+ format)]] + [collection + ["." list ("#\." functor monoid)]]]] + [// + ["." license (#+ Identification + Termination + Liability + Distribution + Commercial + Extension + Entity Black_List + URL Attribution + License) + ["." copyright] + ["." definition (#+ Definition)] + ["." grant] + ["." limitation] + ["." assurance] + ["." liability] + ["." distribution] + ["." commercial] + ["." extension] + ["." submission] + ["." miscellaneous] + ["." black_list] + ["." notice] + ["_" term] + ["." addendum]] + ["$" document]]) + +(def: #export (definition value) + (-> Definition Text) + (format ($.quote (get@ #definition.term value)) ": " (get@ #definition.meaning value))) + +(def: #export (identification value) + (-> Identification Text) + (format (get@ #license.name value) text.new_line + (get@ #license.version value))) + +(def: #export (grant termination) + (-> Termination Text) + (`` (format (~~ (template [<title> <content>] + [($.block ($.section {#$.title <title> + #$.content <content>}))] + + ["Grant of Copyright License" + grant.copyright] + + ["Grant of Patent License" + (grant.patent (get@ #license.patent_retaliation? termination))] + + ["Effective Date for the Grants" + grant.date] + + ["Grant Termination" + (grant.termination (get@ #license.termination_period termination) + (get@ #license.grace_period termination))] + + ["No Retroactive Effect of Termination" + grant.no_retroactive_termination]))))) + +(def: #export limitation + Text + (`` (format (~~ (template [<title> <content>] + [($.block ($.section {#$.title <title> + #$.content <content>}))] + + ["Limitations on Grant Scope" + limitation.grant] + + ["Limitations on Trademarks" + limitation.trademark] + + [(format "Limitations on " ($.plural _.secondary_license)) + limitation.secondary_licenses]))))) + +(def: #export assurance + Text + (`` (format (~~ (template [<title> <content>] + [($.block ($.section {#$.title <title> + #$.content <content>}))] + + ["Representation" + assurance.representation] + + ["Fair Use" + assurance.fair_use]))))) + +(def: #export (liability value) + (-> Liability Text) + (`` (format (~~ (template [<title> <condition> <content>] + [(if <condition> + ($.block ($.section {#$.title <title> + #$.content <content>})) + "")] + + ["Disclaimer of Warranty" + on + liability.warranty] + + ["Limitation of Liability" + on + liability.limitation] + + ["Litigation" + on + liability.litigation] + + ["Accepting Warranty or Additional Liability" + (get@ #license.can_accept? value) + liability.can_accept] + + ["High Risk Activities" + (get@ #license.disclaim_high_risk? value) + liability.disclaim_high_risk]))))) + +(def: #export (distribution distribution) + (-> Distribution Text) + (`` (format (~~ (template [<title> <condition> <content>] + [(if <condition> + ($.block ($.section {#$.title <title> + #$.content <content>})) + "")] + + [(format "Distribution of a " _.source_code_form) + on + distribution.source_code_form] + + [(format "Distribution of an " _.object_form) + on + distribution.object_form] + + [(format "Distribution of an " _.extension) + (or (get@ #license.can_re_license? distribution) + (get@ #license.can_multi_license? distribution)) + (distribution.extension distribution)]))))) + +(def: #export (commercial value) + (-> Commercial Text) + (`` (format (~~ (template [<title> <condition> <content>] + [(if <condition> + ($.block ($.section {#$.title <title> + #$.content <content>})) + "")] + + ["Non-Commerciality" + (not (get@ #license.can_sell? value)) + commercial.cannot_sell] + + [(format _.contributor " Attribution") + (get@ #license.require_contributor_credit? value) + commercial.require_contributor_attribution] + + [(format _.contributor " Endorsement") + (not (get@ #license.allow_contributor_endorsement? value)) + commercial.disallow_contributor_endorsement] + ))))) + +(def: #export (extension value) + (-> Extension Text) + (let [[show? document] (case (get@ #license.notification_period value) + (#.Some period) + [true (extension.notification_requirement period)] + + #.None + [false ""])] + (`` (format (~~ (template [<condition> <title> <content>] + [(if <condition> + ($.block ($.section {#$.title <title> + #$.content <content>})) + "")] + + [(get@ #license.same_license? value) "License Retention" + ($.paragraph (list\compose extension.sharing_requirement + extension.license_conflict_resolution))] + + [(get@ #license.must_be_distinguishable? value) (format _.extension " Distinctness") + extension.distinctness_requirement] + + [show? (format _.source_code_form " Availability") + document] + + [(get@ #license.must_describe_modifications? value) (format "Description of " ($.plural _.modification)) + extension.description_requirement])))))) + +(def: #export (attribution value) + (-> Attribution Text) + (let [copyright_notice (format "Attribution Copyright Notice: " (get@ #license.copyright_notice value)) + phrase (case (get@ #license.phrase value) + (#.Some phrase) + (format text.new_line "Attribution Phrase: " phrase text.new_line) + + #.None + "") + url (format text.new_line "Attribution URL: " (get@ #license.url value)) + image (case (get@ #license.image value) + (#.Some image) + (format text.new_line "Attribution Image: " image) + + #.None + "")] + (format copyright_notice + phrase + url + image))) + +(def: #export (miscellaneous identified?) + (-> Bit Text) + (`` (format (~~ (template [<title> <condition> <content>] + [(if <condition> + ($.block ($.section {#$.title <title> + #$.content <content>})) + "")] + + ["Entire Agreement" + on + miscellaneous.entire_agreement] + + ["Relationship of Parties" + on + miscellaneous.relationship_of_parties] + + ["Independent Development" + on + miscellaneous.independent_development] + + ["Consent To Breach Not Waiver" + on + miscellaneous.not_waiver] + + ["Severability" + on + miscellaneous.severability] + + ["Export Restrictions" + on + miscellaneous.export_restrictions] + + [(format "Versions of " _.license) + identified? + miscellaneous.new_versions] + ))))) + +(def: black_list_spacing (format text.new_line text.new_line)) + +(def: #export (license value) + (-> License Text) + (let [identification (|> value + (get@ #license.identification) + (maybe\map ..identification) + (maybe.default "")) + identified? (case (get@ #license.identification value) + (#.Some _) + true + + #.None + false)] + (`` (format ($.block identification) + ($.block (notice.copyright (get@ #license.copyright_holders value))) + + (case (get@ #license.black_lists value) + #.Nil + "" + + black_lists + ($.block ($.section {#$.title (format "Denial of " _.license) + #$.content (|> black_lists + (list\map black_list.black_list) + (text.join_with ..black_list_spacing))}))) + + ($.section {#$.title "Definitions" + #$.content (|> definition.all + (list\map (|>> ..definition $.block)) + (text.join_with ""))}) + + ($.block ($.section {#$.title (format "Acceptance of " _.license) + #$.content limitation.acceptance})) + + (..grant (get@ #license.termination value)) + ..limitation + ..assurance + + ($.block ($.section {#$.title (format _.submission " of " ($.plural _.contribution)) + #$.content submission.contribution})) + + (..liability (get@ #license.liability value)) + (..distribution (get@ #license.distribution value)) + (..commercial (get@ #license.commercial value)) + (..extension (get@ #license.extension value)) + + (|> value + (get@ #license.attribution) + (maybe\map (|>> ..attribution + ["Attribution Information"] + $.section + $.block)) + (maybe.default "")) + + (..miscellaneous identified?) + + (addendum.output (get@ #license.addendum value)) + + notice.end_of_license + )))) diff --git a/licentia/source/test/licentia.lux b/licentia/source/test/licentia.lux new file mode 100644 index 000000000..bf0f4929e --- /dev/null +++ b/licentia/source/test/licentia.lux @@ -0,0 +1,368 @@ +(.module: + [lux #* + [program (#+ program:)] + ["_" test (#+ Test)] + [abstract + [monad (#+ do)]] + [control + [io (#+ io)]] + [data + ["." bit ("#\." equivalence)] + ["." maybe ("#\." functor)] + ["." text] + [collection + ["." list ("#\." functor)]]] + [math + ["." random (#+ Random)] + [number + ["n" nat ("#\." interval)]]]] + {#program + [/ + ["." license (#+ Identification + Termination + Liability + Distribution + Commercial + Extension + Entity Black_List + URL Attribution + Addendum + License) + ["." time (#+ Period)] + ["." copyright] + ["." notice] + ["." definition] + ["." grant] + ["." limitation] + ["." submission] + ["." liability] + ["." distribution] + ["." commercial] + ["." extension] + ["." miscellaneous] + ["." black_list] + ["." addendum]] + ["." output]]}) + +(def: period + (Random (Period Nat)) + (do {! random.monad} + [start (random.filter (|>> (n.= n\top) not) + random.nat) + #let [wiggle_room (n.- start n\top)] + end (\ ! map + (|>> (n.% wiggle_room) (n.max 1)) + random.nat)] + (wrap {#time.start start + #time.end end}))) + +(def: copyright_holder + (Random copyright.Holder) + ($_ random.and + (random.ascii 10) + ..period)) + +(def: identification + (Random Identification) + ($_ random.and + (random.ascii 10) + (random.ascii 10))) + +(def: termination + (Random Termination) + ($_ random.and + random.bit + random.nat + random.nat)) + +(def: liability + (Random Liability) + ($_ random.and + random.bit + random.bit)) + +(def: distribution + (Random Distribution) + ($_ random.and + random.bit + random.bit)) + +(def: commercial + (Random Commercial) + ($_ random.and + random.bit + random.bit + random.bit)) + +(def: extension + (Random Extension) + ($_ random.and + random.bit + random.bit + (random.maybe ..period) + random.bit)) + +(def: entity + (Random Entity) + (random.ascii 10)) + +(def: (variable_list max_size gen_element) + (All [a] (-> Nat (Random a) (Random (List a)))) + (do {! random.monad} + [amount (\ ! map (n.% (n.max 1 max_size)) + random.nat)] + (random.list amount gen_element))) + +(def: black_list + (Random Black_List) + ($_ random.and + (random.maybe (random.ascii 10)) + (variable_list 10 ..entity))) + +(def: url + (Random URL) + (random.ascii 10)) + +(def: attribution + (Random Attribution) + ($_ random.and + (random.ascii 10) + (random.maybe (random.ascii 10)) + ..url + (random.maybe ..url))) + +(def: addendum + (Random Addendum) + ($_ random.and + random.bit + )) + +(def: license + (Random License) + ($_ random.and + (random.list 2 ..copyright_holder) + (random.maybe ..identification) + ..termination + ..liability + ..distribution + ..commercial + ..extension + (variable_list 3 ..black_list) + (random.maybe attribution) + ..addendum + )) + +(type: (Concern a) + (-> (-> Text Bit) a Test)) + +(def: (about_grant present? termination) + (Concern Termination) + ($_ _.and + (_.test "Copyright grant is present." + (present? grant.copyright)) + (_.test "Patent grant is present." + (present? (grant.patent (get@ #license.patent_retaliation? termination)))) + (_.test "Effective date for the grants is present." + (present? grant.date)) + (_.test "Patent grant is present." + (present? (grant.termination (get@ #license.termination_period termination) + (get@ #license.grace_period termination)))) + (_.test "The termination period is accurately conveyed." + (present? (grant.grant_restoration_clause (get@ #license.termination_period termination)))) + (_.test "The grace period is accurately conveyed." + (present? (grant.grace_period_clause (get@ #license.grace_period termination)))) + (_.test "The grants are not retro-actively terminated." + (present? grant.no_retroactive_termination)) + )) + +(def: (about_liability present? liability) + (Concern Liability) + ($_ _.and + (_.test "Warranty liability disclaimer is present." + (present? liability.warranty)) + (_.test "Limitation of liability is present." + (present? liability.limitation)) + (_.test "Litigation conditions are present." + (present? liability.litigation)) + (_.test "Liability acceptance conditions may be present." + (bit\= (get@ #license.can_accept? liability) + (present? liability.can_accept))) + (_.test "Liability acceptance conditions may be present." + (bit\= (get@ #license.disclaim_high_risk? liability) + (present? liability.disclaim_high_risk))) + )) + +(def: (about_distribution present? distribution) + (Concern Distribution) + ($_ _.and + (_.test "Conditions for source-code distribution are present." + (present? distribution.source_code_form)) + (_.test "Conditions for object-code distribution are present." + (present? distribution.object_form)) + (_.test "Conditions for extension distribution are present." + (present? (distribution.extension distribution))) + )) + +(def: (about_commercial present? commercial) + (Concern Commercial) + ($_ _.and + (_.test "Non-commercial clause is present." + (bit\= (not (get@ #license.can_sell? commercial)) + (present? commercial.cannot_sell))) + (_.test "Contributor credit condition is present." + (bit\= (get@ #license.require_contributor_credit? commercial) + (present? commercial.require_contributor_attribution))) + (_.test "Anti-endorsement condition is present." + (bit\= (not (get@ #license.allow_contributor_endorsement? commercial)) + (present? commercial.disallow_contributor_endorsement))) + )) + +(def: (about_extension present? extension) + (Concern Extension) + ($_ _.and + (_.test "The license is viral." + (bit\= (get@ #license.same_license? extension) + (and (list.every? present? extension.sharing_requirement) + (list.every? present? extension.license_conflict_resolution)))) + (_.test "Extensions must be distinguishable from the original work." + (bit\= (get@ #license.must_be_distinguishable? extension) + (present? extension.distinctness_requirement))) + (_.test "The community must be notified of new extensions." + (case (get@ #license.notification_period extension) + (#.Some period) + (present? (extension.notification_requirement period)) + + #.None + true)) + (_.test "Must describe modifications." + (bit\= (get@ #license.must_describe_modifications? extension) + (present? extension.description_requirement))) + )) + +(def: (about_attribution present? attribution) + (Concern Attribution) + ($_ _.and + (_.test "The attribution copyright notice is present." + (present? (get@ #license.copyright_notice attribution))) + (_.test "The attribution phrase is present." + (|> attribution + (get@ #license.phrase) + (maybe\map present?) + (maybe.default true))) + (_.test "The attribution URL is present." + (present? (get@ #license.url attribution))) + (_.test "The attribution image is present." + (|> attribution + (get@ #license.image) + (maybe\map present?) + (maybe.default true))) + )) + +(def: (about_miscellaneous present?) + (-> (-> Text Bit) Test) + ($_ _.and + (_.test "License constitutes the entire agreement." + (present? miscellaneous.entire_agreement)) + (_.test "Disclaims relationship of parties." + (present? miscellaneous.relationship_of_parties)) + (_.test "Explicitly allows independent development." + (present? miscellaneous.independent_development)) + (_.test "Clarifies consent to breach does not waiver." + (present? miscellaneous.not_waiver)) + (_.test "Provides severability." + (present? miscellaneous.severability)) + (_.test "Covers export restrictions." + (present? miscellaneous.export_restrictions)) + )) + +(def: (about_addendum present? value) + (Concern Addendum) + ($_ _.and + (_.test "Commons clause" + (bit\= (get@ #license.commons_clause? value) + (present? addendum.commons_clause))) + )) + +(def: test + Test + (do random.monad + [license ..license + #let [writ (output.license license) + present? (: (-> Text Bit) + (function (_ snippet) + (text.contains? snippet writ)))]] + ($_ _.and + (_.test "Copyright notices are present." + (list.every? (|>> notice.copyright_holder present?) + (get@ #license.copyright_holders license))) + + (_.test "Identification is present (if the license is identified)." + (case (get@ #license.identification license) + (#.Some identification) + (and (present? (output.identification identification)) + (present? miscellaneous.new_versions)) + + #.None + (not (present? miscellaneous.new_versions)))) + + (_.test "Black-lists (if wanted by licensor) are explicitly enumerated and justified." + (list.every? (function (_ black_list) + (let [black_list_is_justified? (case (get@ #license.justification black_list) + (#.Some justification) + (present? justification) + + #.None + yes) + every_entity_is_mentioned? (|> black_list + (get@ #license.entities) + (list\map black_list.entity) + (list.every? present?))] + (and black_list_is_justified? + every_entity_is_mentioned?))) + (get@ #license.black_lists license))) + + (_.test "All definitions are present." + (list.every? (|>> output.definition present?) + definition.all)) + + (_.test "Acceptance of the license is demanded." + (present? limitation.acceptance)) + + (..about_grant present? (get@ #license.termination license)) + + (_.test "All limitations are present." + (present? output.limitation)) + + (_.test "All assurances are present." + (present? output.assurance)) + + (_.test "The terms of submission are present." + (present? submission.contribution)) + + (..about_liability present? (get@ #license.liability license)) + + (..about_distribution present? (get@ #license.distribution license)) + + (..about_commercial present? (get@ #license.commercial license)) + + (..about_extension present? (get@ #license.extension license)) + + (case (get@ #license.attribution license) + (#.Some attribution) + (..about_attribution present? attribution) + + #.None + (_.test "Attribution is missing." + yes)) + + (..about_miscellaneous present?) + + (..about_addendum present? (get@ #license.addendum license)) + + (_.test "License ending footer is present." + (present? notice.end_of_license)) + ))) + +(program: args + (io (_.run! (<| (_.times 100) + ..test)))) -- cgit v1.2.3