diff --git a/bin/ci_browser_foundation.grease b/bin/ci_browser_foundation.grease index b37fa92..b8867e6 100755 --- a/bin/ci_browser_foundation.grease +++ b/bin/ci_browser_foundation.grease @@ -19,13 +19,13 @@ build_idric() { git -C /tmp/Idric checkout --detach -q FETCH_HEAD test "$(git -C /tmp/Idric rev-parse HEAD)" = "$idric_ref" - idric_build_root=/tmp/Idric - if [ -f /tmp/Idric/_/Makefile ]; then - idric_build_root=/tmp/Idric/_ - fi - - SCHEME=chezscheme make -C "$idric_build_root" bootstrap PREFIX="$idric_prefix" - SCHEME=chezscheme make -C "$idric_build_root" install PREFIX="$idric_prefix" + # Current Edric owns its bootstrap/build machinery below _/. Use the stable + # top-level entrypoint rather than depending on the old root Makefile layout. + PREFIX="$idric_prefix" sh /tmp/Idric/edric bootstrap + make -C /tmp/Idric/_ install \ + PREFIX="$idric_prefix" \ + SCHEME=/tmp/Idric/_/.tools/bin/scheme + test -x "$idric_prefix/bin/idris2" } verify_pdf_harvester() { diff --git a/src/CanonicalInformationSmoke.idric b/src/CanonicalInformationSmoke.idric index e97a82b..15ce11f 100644 --- a/src/CanonicalInformationSmoke.idric +++ b/src/CanonicalInformationSmoke.idric @@ -1,35 +1,38 @@ module CanonicalInformationSmoke -import IB.Information.Model -import IB.Prepaint.Model +import IB.Strand +import IB.Prepaint import IB.Prepaint.Version1 %default total fixture_strand : Maybe Strand fixture_strand = do - source_reference <- nonempty_text "fixture:strand-1" - requested <- requested_address "https://example.test/requested" - resolved <- resolved_address "https://example.test/resolved" - image <- fetched_image "asset:figure-1" - let source = Source source_reference HtmlRepresentation CompleteRepresentation + source_reference ← nonempty_text "fixture:strand-1" + requested ← requested_address "https://example.test/requested" + resolved ← resolved_address "https://example.test/resolved" + image ← image_reference "asset:figure-1" + next_link ← link_reference "/next" + search_form ← form_reference "/search" + figure_link ← link_reference "/figure/1" + let source = Source source_reference HtmlSource CompleteSource pure (MakeStrand source requested resolved (Just "Example") - [ InformationHeading Heading2 "Section" - , InformationText "Visible paragraph" - , InformationLink "Next" (LinkReference "/next") - , InformationTableRow (TableCells "first" ["second"]) - , InformationForm "Search" (FormReference "/search") - , InformationImage image "diagram" "Figure 1" (Just (LinkReference "/figure/1")) + [ Heading Heading2 "Section" + , Text "Visible paragraph" + , Link "Next" next_link + , TableRow (table_row "first" ["second"]) + , Form "Search" search_form + , Image image "diagram" "Figure 1" (Just figure_link) ]) empty_image_refused : Bool empty_image_refused = - case fetched_image "" of + case image_reference "" of Nothing ⇒ True Just _ ⇒ False @@ -41,8 +44,8 @@ seventh_heading_refused = nonincreasing_revision_refused : Strand → Bool nonincreasing_revision_refused strand = - let first = revision_from_strand (Revision 1) PartialRevision strand in - let second = revision_from_strand (Revision 1) CompleteRevision strand in + let first = prepaint_from_strand first_revision PartialRevision strand in + let second = prepaint_from_strand first_revision CompleteRevision strand in case serialize_version1 [first, second] of Nothing ⇒ True Just _ ⇒ False @@ -55,12 +58,12 @@ version1_result (Just version1_text) = strand_report : Strand → String strand_report strand = - let partial = revision_from_strand (Revision 0) PartialRevision strand in - let complete = revision_from_strand (Revision 1) CompleteRevision strand in + let partial = prepaint_from_strand first_revision PartialRevision strand in + let complete = prepaint_from_strand (next_revision first_revision) CompleteRevision strand in unlines [ "canonical-information=constructed" , "canonical-blocks=" ++ show (length strand.blocks) - , "canonical-row-cells=" ++ show (length (table_row_cells (TableCells "first" ["second"]))) + , "canonical-row-cells=" ++ show (length (table_row_cells (table_row "first" ["second"]))) , "empty-image-refused=" ++ show empty_image_refused , "seventh-heading-refused=" ++ show seventh_heading_refused , "revision-zero=" ++ show (revision_sequence_value partial.sequence) diff --git a/src/IB/Information/Model.idric b/src/IB/Information/Model.idric deleted file mode 100644 index 383cd2b..0000000 --- a/src/IB/Information/Model.idric +++ /dev/null @@ -1,137 +0,0 @@ -module IB.Information.Model - -%default total - -public export -data NonemptyText = TextBeginning Char (List Char) - -public export -nonempty_text : String → Maybe NonemptyText -nonempty_text value = - case unpack value of - [] => Nothing - first :: rest => Just (TextBeginning first rest) - -public export -nonempty_text_value : NonemptyText → String -nonempty_text_value (TextBeginning first rest) = pack (first :: rest) - -public export -data RepresentationOrigin - = HtmlRepresentation - | PdfRepresentation - | PlainTextRepresentation - | DerivedRepresentation - | OtherRepresentation - -public export -data RepresentationCompleteness - = PartialRepresentation - | CompleteRepresentation - -public export -record SourceRepresentation where - constructor Source - reference : NonemptyText - origin : RepresentationOrigin - completeness : RepresentationCompleteness - -public export -data RequestedAddressText = RequestedAddress NonemptyText - -public export -data ResolvedAddressText = ResolvedAddress NonemptyText - -public export -data LinkReferenceText = LinkReference String - -public export -data FormReferenceText = FormReference String - -public export -data FetchedImageReference = FetchedImage NonemptyText - -public export -requested_address : String → Maybe RequestedAddressText -requested_address value = map RequestedAddress (nonempty_text value) - -public export -resolved_address : String → Maybe ResolvedAddressText -resolved_address value = map ResolvedAddress (nonempty_text value) - -public export -fetched_image : String → Maybe FetchedImageReference -fetched_image value = map FetchedImage (nonempty_text value) - -public export -requested_address_value : RequestedAddressText → String -requested_address_value (RequestedAddress value) = nonempty_text_value value - -public export -resolved_address_value : ResolvedAddressText → String -resolved_address_value (ResolvedAddress value) = nonempty_text_value value - -public export -link_reference_value : LinkReferenceText → String -link_reference_value (LinkReference value) = value - -public export -form_reference_value : FormReferenceText → String -form_reference_value (FormReference value) = value - -public export -fetched_image_value : FetchedImageReference → String -fetched_image_value (FetchedImage value) = nonempty_text_value value - -public export -data HeadingLevel - = Heading1 - | Heading2 - | Heading3 - | Heading4 - | Heading5 - | Heading6 - -public export -heading_level_number : HeadingLevel → Nat -heading_level_number Heading1 = 1 -heading_level_number Heading2 = 2 -heading_level_number Heading3 = 3 -heading_level_number Heading4 = 4 -heading_level_number Heading5 = 5 -heading_level_number Heading6 = 6 - -public export -heading_level : Nat → Maybe HeadingLevel -heading_level 1 = Just Heading1 -heading_level 2 = Just Heading2 -heading_level 3 = Just Heading3 -heading_level 4 = Just Heading4 -heading_level 5 = Just Heading5 -heading_level 6 = Just Heading6 -heading_level _ = Nothing - -public export -data NonemptyTableRow = TableCells String (List String) - -public export -table_row_cells : NonemptyTableRow → List String -table_row_cells (TableCells first rest) = first :: rest - -public export -data InformationBlock - = InformationHeading HeadingLevel String - | InformationText String - | InformationLink String LinkReferenceText - | InformationTableRow NonemptyTableRow - | InformationForm String FormReferenceText - | InformationImage FetchedImageReference String String (Maybe LinkReferenceText) - -public export -record Strand where - constructor MakeStrand - source : SourceRepresentation - requested : RequestedAddressText - resolved : ResolvedAddressText - title : Maybe String - blocks : List InformationBlock diff --git a/src/IB/Prepaint.idric b/src/IB/Prepaint.idric new file mode 100644 index 0000000..b3d124f --- /dev/null +++ b/src/IB/Prepaint.idric @@ -0,0 +1,51 @@ +module IB.Prepaint + +import IB.Strand + +%default total + +-- Revision numbers are generated here rather than exposed as an unrestricted +-- machine count. Zero is the first valid revision and next_revision is the +-- only public way to advance it. +export +data RevisionSequence = Revision Integer + +export +first_revision : RevisionSequence +first_revision = Revision 0 + +export +next_revision : RevisionSequence → RevisionSequence +next_revision (Revision value) = Revision (value + 1) + +export +revision_sequence_value : RevisionSequence → Integer +revision_sequence_value (Revision value) = value + +public export +data RevisionState + = PartialRevision + | CompleteRevision + +public export +record PrepaintRevision where + constructor Prepaint + sequence : RevisionSequence + state : RevisionState + source : SourceRepresentation + requested : RequestedAddress + resolved : ResolvedAddress + title : Maybe String + blocks : List InformationBlock + +export +prepaint_from_strand : RevisionSequence → RevisionState → Strand → PrepaintRevision +prepaint_from_strand sequence state strand = + Prepaint + sequence + state + strand.source + strand.requested + strand.resolved + strand.title + strand.blocks diff --git a/src/IB/Prepaint/Model.idric b/src/IB/Prepaint/Model.idric deleted file mode 100644 index d94f0f2..0000000 --- a/src/IB/Prepaint/Model.idric +++ /dev/null @@ -1,40 +0,0 @@ -module IB.Prepaint.Model - -import IB.Information.Model - -%default total - -public export -data RevisionSequence = Revision Nat - -public export -revision_sequence_value : RevisionSequence → Nat -revision_sequence_value (Revision value) = value - -public export -data RevisionState - = PartialRevision - | CompleteRevision - -public export -record PrepaintRevision where - constructor Prepaint - sequence : RevisionSequence - state : RevisionState - source : SourceRepresentation - requested : RequestedAddressText - resolved : ResolvedAddressText - title : Maybe String - blocks : List InformationBlock - -public export -revision_from_strand : RevisionSequence → RevisionState → Strand → PrepaintRevision -revision_from_strand sequence state strand = - Prepaint - sequence - state - strand.source - strand.requested - strand.resolved - strand.title - strand.blocks diff --git a/src/IB/Prepaint/Version1.idric b/src/IB/Prepaint/Version1.idric index 90fc839..91bf801 100644 --- a/src/IB/Prepaint/Version1.idric +++ b/src/IB/Prepaint/Version1.idric @@ -1,7 +1,7 @@ module IB.Prepaint.Version1 -import IB.Information.Model -import IB.Prepaint.Model +import IB.Strand +import IB.Prepaint %default total @@ -25,12 +25,7 @@ join_fields [value] = value join_fields (value :: rest) = value ++ "\t" ++ join_fields rest heading_level_text : HeadingLevel → String -heading_level_text Heading1 = "1" -heading_level_text Heading2 = "2" -heading_level_text Heading3 = "3" -heading_level_text Heading4 = "4" -heading_level_text Heading5 = "5" -heading_level_text Heading6 = "6" +heading_level_text level = show (heading_level_number level) revision_state_text : RevisionState → String revision_state_text PartialRevision = "partial" @@ -41,33 +36,33 @@ maybe_text Nothing = "" maybe_text (Just value) = value serialize_block : InformationBlock → String -serialize_block (InformationHeading level text) = +serialize_block (Heading level text) = join_fields ["heading", heading_level_text level, escape_field text] -serialize_block (InformationText text) = +serialize_block (Text text) = join_fields ["text", escape_field text] -serialize_block (InformationLink text reference) = +serialize_block (Link text reference) = join_fields ["link", escape_field text, escape_field (link_reference_value reference)] -serialize_block (InformationTableRow row) = +serialize_block (TableRow row) = join_fields ("row" :: map escape_field (table_row_cells row)) -serialize_block (InformationForm text reference) = +serialize_block (Form text reference) = join_fields ["form", escape_field text, escape_field (form_reference_value reference)] -serialize_block (InformationImage source alternate caption Nothing) = +serialize_block (Image source alternate caption Nothing) = join_fields [ "image" - , escape_field (fetched_image_value source) + , escape_field (image_reference_value source) , escape_field alternate , escape_field caption ] -serialize_block (InformationImage source alternate caption (Just reference)) = +serialize_block (Image source alternate caption (Just reference)) = join_fields [ "image" - , escape_field (fetched_image_value source) + , escape_field (image_reference_value source) , escape_field alternate , escape_field caption , escape_field (link_reference_value reference) ] -public export +export serialize_revision : PrepaintRevision → List String serialize_revision revision = join_fields @@ -80,18 +75,19 @@ serialize_revision revision = join_fields ["title", escape_field (maybe_text revision.title)] :: map serialize_block revision.blocks ++ ["end"] -strictly_after : Nat → PrepaintRevision → Bool -strictly_after previous revision = previous < revision_sequence_value revision.sequence +strictly_after : RevisionSequence → PrepaintRevision → Bool +strictly_after previous revision = + revision_sequence_value previous < revision_sequence_value revision.sequence -serialize_revisions : Maybe Nat → List PrepaintRevision → Maybe (List String) +serialize_revisions : Maybe RevisionSequence → List PrepaintRevision → Maybe (List String) serialize_revisions previous [] = Just [] serialize_revisions Nothing (revision :: rest) = do - remaining <- serialize_revisions (Just (revision_sequence_value revision.sequence)) rest + remaining ← serialize_revisions (Just revision.sequence) rest pure (serialize_revision revision ++ remaining) serialize_revisions (Just previous) (revision :: rest) = if strictly_after previous revision then do - remaining <- serialize_revisions (Just (revision_sequence_value revision.sequence)) rest + remaining ← serialize_revisions (Just revision.sequence) rest pure (serialize_revision revision ++ remaining) else Nothing @@ -99,8 +95,8 @@ join_lines : List String → String join_lines [] = "" join_lines (line :: rest) = line ++ "\n" ++ join_lines rest -public export +export serialize_version1 : List PrepaintRevision → Maybe String serialize_version1 revisions = do - body <- serialize_revisions Nothing revisions + body ← serialize_revisions Nothing revisions pure (join_lines (join_fields ["ib-prepaint", "1"] :: body)) diff --git a/src/IB/Strand.idric b/src/IB/Strand.idric new file mode 100644 index 0000000..2fe7617 --- /dev/null +++ b/src/IB/Strand.idric @@ -0,0 +1,151 @@ +module IB.Strand + +%default total + +-- These wrappers keep empty filesystem, source, address, and resource names out +-- of the semantic strand. Their representations stay private to this module. +export +data NonemptyText = TextBeginning Char (List Char) + +export +nonempty_text : String → Maybe NonemptyText +nonempty_text value = + case unpack value of + [] ⇒ Nothing + first :: rest ⇒ Just (TextBeginning first rest) + +export +nonempty_text_value : NonemptyText → String +nonempty_text_value (TextBeginning first rest) = pack (first :: rest) + +public export +data RepresentationOrigin + = HtmlSource + | PdfSource + | PlainTextSource + | DerivedSource + | OtherSource + +public export +data RepresentationCompleteness + = PartialSource + | CompleteSource + +public export +record SourceRepresentation where + constructor Source + reference : NonemptyText + origin : RepresentationOrigin + completeness : RepresentationCompleteness + +export +data RequestedAddress = Requested NonemptyText + +export +data ResolvedAddress = Resolved NonemptyText + +export +data LinkReference = LinkTo NonemptyText + +export +data FormReference = SubmitTo NonemptyText + +export +data ImageReference = ImageAt NonemptyText + +export +requested_address : String → Maybe RequestedAddress +requested_address value = map Requested (nonempty_text value) + +export +resolved_address : String → Maybe ResolvedAddress +resolved_address value = map Resolved (nonempty_text value) + +export +link_reference : String → Maybe LinkReference +link_reference value = map LinkTo (nonempty_text value) + +export +form_reference : String → Maybe FormReference +form_reference value = map SubmitTo (nonempty_text value) + +export +image_reference : String → Maybe ImageReference +image_reference value = map ImageAt (nonempty_text value) + +export +requested_address_value : RequestedAddress → String +requested_address_value (Requested value) = nonempty_text_value value + +export +resolved_address_value : ResolvedAddress → String +resolved_address_value (Resolved value) = nonempty_text_value value + +export +link_reference_value : LinkReference → String +link_reference_value (LinkTo value) = nonempty_text_value value + +export +form_reference_value : FormReference → String +form_reference_value (SubmitTo value) = nonempty_text_value value + +export +image_reference_value : ImageReference → String +image_reference_value (ImageAt value) = nonempty_text_value value + +public export +data HeadingLevel + = Heading1 + | Heading2 + | Heading3 + | Heading4 + | Heading5 + | Heading6 + +export +heading_level_number : HeadingLevel → Integer +heading_level_number Heading1 = 1 +heading_level_number Heading2 = 2 +heading_level_number Heading3 = 3 +heading_level_number Heading4 = 4 +heading_level_number Heading5 = 5 +heading_level_number Heading6 = 6 + +export +heading_level : Integer → Maybe HeadingLevel +heading_level 1 = Just Heading1 +heading_level 2 = Just Heading2 +heading_level 3 = Just Heading3 +heading_level 4 = Just Heading4 +heading_level 5 = Just Heading5 +heading_level 6 = Just Heading6 +heading_level _ = Nothing + +export +data NonemptyTableRow = TableCells String (List String) + +export +table_row : String → List String → NonemptyTableRow +table_row first remaining = TableCells first remaining + +export +table_row_cells : NonemptyTableRow → List String +table_row_cells (TableCells first remaining) = first :: remaining + +public export +data InformationBlock + = Heading HeadingLevel String + | Text String + | Link String LinkReference + | TableRow NonemptyTableRow + | Form String FormReference + | Image ImageReference String String (Maybe LinkReference) + +public export +record Strand where + constructor MakeStrand + source : SourceRepresentation + requested : RequestedAddress + resolved : ResolvedAddress + title : Maybe String + blocks : List InformationBlock