Karya, built on 2020-11-26T21:03:17 (patch 23b5be2d53a9e8e7d6136cda5aae2849abe5cded)
Safe HaskellNone



This ties together the lower level tscore components.

Parse tscore, check and postprocess it, convert to Ui.State, and integrate.



data Block track Source #





Instances details
Functor Block # 
Instance details

Defined in Derive.TScore.TScore


fmap :: (a -> b) -> Block a -> Block b #

(<$) :: a -> Block b -> Block a #

Eq track => Eq (Block track) # 
Instance details

Defined in Derive.TScore.TScore


(==) :: Block track -> Block track -> Bool #

(/=) :: Block track -> Block track -> Bool #

Show track => Show (Block track) # 
Instance details

Defined in Derive.TScore.TScore


showsPrec :: Int -> Block track -> ShowS #

show :: Block track -> String #

showList :: [Block track] -> ShowS #

Pretty.Pretty track => Pretty.Pretty (Block track) # 
Instance details

Defined in Derive.TScore.TScore


pretty :: Block track -> Text Source #

format :: Block track -> Doc Source #

formatList :: [Block track] -> Doc Source #

data NTrack Source #

A tscore track consists of multiple tracklang tracks, since it includes both rhythm and pitch.




  • _note :: !Track
  • _key :: !Text
  • _controls :: ![Track]
  • _end :: T.Time

    End of the track. This could be past the end of the last event if there was a rest on the end. This is intentionally not strict, because you should iterate over the tracks and events before looking at it.


Instances details
Eq NTrack # 
Instance details

Defined in Derive.TScore.TScore


(==) :: NTrack -> NTrack -> Bool #

(/=) :: NTrack -> NTrack -> Bool #

Show NTrack # 
Instance details

Defined in Derive.TScore.TScore

Pretty.Pretty NTrack # 
Instance details

Defined in Derive.TScore.TScore

data ParsedTrack Source #

This track has been parsed, and directives propagated to Check.Config, but not yet converted to a Track.


Instances details
Show ParsedTrack # 
Instance details

Defined in Derive.TScore.TScore

data Track Source #

A complete track, ready to be integrated or directly put in a block.





Instances details
Eq Track # 
Instance details

Defined in Derive.TScore.TScore


(==) :: Track -> Track -> Bool #

(/=) :: Track -> Track -> Bool #

Show Track # 
Instance details

Defined in Derive.TScore.TScore


showsPrec :: Int -> Track -> ShowS #

show :: Track -> String #

showList :: [Track] -> ShowS #

Pretty.Pretty Track # 
Instance details

Defined in Derive.TScore.TScore


integrate Source #


:: Ui.M m 
=> GetExternalCallDuration 
-> Text 
-> m [Id.BlockId]

newly created blocks

destroy_subs :: Ui.M m => m () Source #

set_namespace :: Id.Namespace -> Block track -> Block track Source #

Replace the namespace.

I used to put tscore-generated things in Parse.default_namespace, so they wouldn't clash with non-tscore blocks. But then it turns out that means tscore blocks can't call other tscore blocks without qualification! Since I want more seemless integration, I no longer want a separate tscore namespace.

partition_errors :: [Block (Either.Either err track)] -> ([err], [Block track]) Source #

type GetExternalCallDuration = [Text] -> Text -> (Either.Either Error TrackTime, [Log.Msg]) Source #

Get the duration of a block call from the tracklang performance, not tscore.

detect moves

find_block_renames :: Map Id.BlockId Block.Block -> [Block NTrack] -> [(Id.BlockId, Id.BlockId)] Source #

Use a heuristic to see if any blocks have been renamed.

I can't know for sure because tscore is just text, and there's no identetiy for the chunk of test that represents a block. But I do rename blocks often, so I'd like something smarter than making an unrelated copy. I could exit and issue a rename command, but I'd have to also modify the text, and besides the UI seems awkward. So I detect the rename, but you have to just rename the block, not modify any events.

A block is a rename of another one if: - I am its source: An existing one has integrated_manual = "tscore" - With NoteDestinations equal to the ones I would produce. - It was deleted: BlockId is not in current blocks.

I don't care if its actual events differ, because I want to retain local edits across the rename.

resolve blocks

check_recursion :: [Block [Token pitch]] -> Maybe.Maybe Error Source #

Look for recursive block calls. If there are none, it's safe to resolve_blocks.

resolve_blocks :: GetExternalCallDuration -> Text -> [Block ParsedTrack] -> [Block (Either.Either Error NTrack)] Source #

Check and resolve pitches and durations with Check.check.

This has to be interleaved across blocks because T.CallDuration means the duration of a note can depend on the duration of other blocks, and so forth. I can get this interleaved and cached via a lazy memo table, but it's only safe because I previously did check_recursion.

match_asserts :: [Check.AssertCoincident] -> [Check.AssertCoincident] -> [(T.Time, T.Note call pitch dur)] -> Maybe.Maybe T.Error Source #

If an expected assert isn't found, or if I got one that wasn't expected, emit an error with the location.

find_pos :: T.Time -> [(T.Time, T.Note call pitch dur)] -> Maybe.Maybe T.Pos Source #

copy from

check_recursive_copy_from :: [Block ParsedTrack] -> [T.Error] Source #

Each %f must refer to a track without %f. This also forbids non-recursive multiple levels of %f, which resolve_copy_from would handle fine, but I don't mind forbidding those too.

This does a redundant resolve_from since resolve_blocks will do it in again, but it seems like a hassle to try to stash the resolved froms in a Block.

resolve_from :: Map Id.BlockId [track] -> Id.BlockId -> TrackNum -> Check.From -> Either.Either T.Error track Source #

Resolve Check.From to the track it names. On a track %f=n copies from the track number. On a block, %f=name is like a %f on each track with its corresponding track on the given block.

resolve_copy_from :: Maybe.Maybe [ResolvedNote] -> [(T.Time, T.Note T.CallText (T.NPitch (Maybe.Maybe T.PitchText)) T.Time)] -> Either.Either T.Error [ResolvedNote] Source #

Resolve T.CopyFrom.

Since I use the resolve_blocks memo table, they will chain, even though I'd sort of rather they didn't.


reverse_tracks :: Block track -> [track] Source #

Tracks are written in reverse order. This is because when notation is horizontal, it's natural to write higher parts above above lower parts, as with staff notation. But when notation is vertical, it's natural to put higher parts on the right, by analogy to instruments that are layed out that way.


ui_block :: Ui.M m => Block NTrack -> m Id.BlockId Source #

Turn a Block NTrack into a UI block directly. integrate_block does same thing, but does so via the integrate machinery.


unwrap_tracks :: T.WrappedTracks -> Either.Either T.Error (T.Tracks T.Call) Source #

The number of tracks must match, and their titles must match.


resolve_sub_block :: T.Block (T.Tracks T.Call) -> (T.Block (T.Tracks T.CallText), [T.Block (T.Tracks T.CallText)]) Source #

Replace T.SubBlock with T.CallText, and return the generated blocks.

resolve_sub_tokens :: Id.BlockId -> TrackNum -> [T.Token T.Call pitch ndur rdur] -> ResolveM [T.Token T.CallText pitch ndur rdur] Source #

pipe_tweak :: Text -> Text Source #

Add a space so "foo|" -> "foo |", because of the xyz|[a] syntax. But don't add a space if it looks like it's not coming from that syntax, e.g. "x |"[a].

sub_meta :: Text Source #

This marks a sub-block.

local util

add_stack :: Event.Event -> Event.Event Source #

A stack marks these events as being from an integration. Event style uses this, but I think that's all since I have SourceKey hardcoded.