Karya, built on Sun Nov 26 01:04:37 PST 2017 (patch 0a920b2bde70c0cbac8ee09d158064798b61bbe5)

Derive.Sig

Contents

Description

Functions to help define call signatures.

This module, along with the Typecheck.Typecheck class, define a little DSL to express function signatures. Check existing calls for examples.

Argument passing, in an effort to be flexible, got a bit complicated. Each Arg has a name and a possible default. So right off there are three ways to provide an argument:

1. Pass it explicitly.
2. If it is omitted, or _ is passed explicitly, it will be sought in the dynamic environ, under the name <call_name>-<arg_name>. E.g. given a call generator "name" $\args -> call (required "arg1") ... then name-arg1 = 42 | call _ will get 42. Note that it uses the call name, and not the symbol it happens to bound to in this scope. This is because, while you may bind different kinds of trills to tr depending on the needs of the score, the two kinds of trills may have different arguments with different meanings. 3. If it's omitted, and not in the dynamic environ, the default will be used, provided there is one. In addition, an arg may be a BaseTypes.VPControlRef or BaseTypes.ControlRef, which introduces yet another way to provide the value. An argument required_control "c" will pass a BaseTypes.LiteralControl. Technically it's then up to the call to decide what to do with it, but it will likely look it up at its chosen point in time, which means you can provide the value by providing a c control track or binding it explicitly e.g. %c = .5 | call. • To further complicate the matter, the control arg may itself have a default, to relieve the caller from always having to provide that control. So an argument control "c" 0.5 or an explicitly provided control val call %c,.5 will default to 0.5 if the c control is not in scope. Since the arg defaulting and control defaulting are orthogonal, they can be combined: 1. Pass it explicitly with a default: call %c,.5. This is either the value of %c or 0.5. 2. Pass it via the dynamic environ: call-arg1 = %c,.5 | call. This is the same as the above, only the argument is provided implicitly. 3. Fall back on the built-in default: control "c" 0.5 and then just call. I originally envisioned the dynamic environ passing scheme to be a way to default certain arguments within the context of a track, to be used in a relatively ad-hoc way in specific parts of the score (e.g. all trills within this section of melody default to minor thirds), is not limited to numeric types, and is constant in time. A control, however, is intended to capture musical parameters that change in time over the course of the piece, and is numeric or a pitch. So while dynamic environ args are forced to be specific to a certain call by prepending the call's name, control names should generally have more general and abstract names. On the subject of controls, controls (and numeric vals in general) have another layer of complexity since they carry types. For example, here's a gloriously complicated argument: defaulted "speed" (typed_control "tremolo-speed" 10 Score.Real). This argument defaults to %tremolo-speed,10s. If it's not given, it will have the value 10s. If the %tremolo-speed control is in scope but untyped, its values will be interpreted as RealTime. If it's in scope and typed (e.g. with a tremolo-speed:t track), then its values will be interpreted as ScoreTime. Another wrinkle in argument passing is that, in addition to being required, which has no default, or being defaulted, which has a default, they can be defaulted with a default of Nothing. This passes the argument as a Maybe a instead of a and lets the call distinguish whether an argument was provided or not. This is for arguments which are defaulted but need a more complicated defaulting strategy than simply a constant. Synopsis # Documentation data Parser a Source # Instances  # Methodsfmap :: (a -> b) -> Parser a -> Parser b #(<$) :: a -> Parser b -> Parser a # # Methodspure :: a -> Parser a #(<*>) :: Parser (a -> b) -> Parser a -> Parser b #(*>) :: Parser a -> Parser b -> Parser b #(<*) :: Parser a -> Parser b -> Parser a #

type Generator y d = PassedArgs y -> Deriver d Source #

Similar to GeneratorF, but leaves the PassedArgs prev val type free. This is important for val calls, which used Tagged.

type Transformer y d = PassedArgs y -> Deriver d -> Deriver d Source #

Arguments

 :: (a -> Maybe Text) return Just error if there's a problem -> Parser a -> Parser a

Annotate a parser with a check on its value.

parse :: Taggable d => Parser a -> PassedArgs d -> Deriver (Either Error a) Source #

Run a parser against the current derive state.

# parsers

Parser for nullary calls. Either use this with call and callt, or use call0 and call0t as a shortcut.

required :: forall a. Typecheck.Typecheck a => ArgName -> Doc.Doc -> Parser a Source #

The argument is required to be present, and have the right type.

defaulted :: forall a. (Typecheck.Typecheck a, ShowVal.ShowVal a) => ArgName -> a -> Doc.Doc -> Parser a Source #

The argument is not required to be present, but if it is, it has to have either the right type or be VNotGiven.

defaulted_env_quoted :: forall a. (Typecheck.Typecheck a, ShowVal.ShowVal a) => ArgName -> EnvironDefault -> BaseTypes.Quoted -> Doc.Doc -> Parser a Source #

The defaulted value can be a BaseTypes.Quoted, which will be evaluated if needed.

This is either required or defaulted, depending on if there's a default value. Useful for making call variants with instrument-specific defaults.

Arguments

 :: (Typecheck.Typecheck a, ShowVal.ShowVal a) => ArgName -> EnvironDefault None doesn't make any sense, but, well, don't pass that then. -> a -> Doc.Doc -> Parser a

This is an argument which is not actually parsed from the argument list. Instead it's looked up it the environ according to the normal defaulting rules.

Of course, the call could just look in the environ itself, but this way it's uniform and automatically documented.

environ_key :: (Typecheck.Typecheck a, ShowVal.ShowVal a) => Key -> a -> Doc.Doc -> Parser a Source #

A shortcut for an unprefixed environ key.

environ_quoted :: forall a. (Typecheck.Typecheck a, ShowVal.ShowVal a) => ArgName -> EnvironDefault -> BaseTypes.Quoted -> Doc.Doc -> Parser a Source #

This is like environ, but the default is a BaseTypes.Quoted, which will be evaluated if needed.

required_environ :: forall a. Typecheck.Typecheck a => ArgName -> EnvironDefault -> Doc.Doc -> Parser a Source #

This is like environ, but without a default.

optional :: forall a. (Typecheck.Typecheck a, ShowVal.ShowVal a) => ArgName -> a -> Doc.Doc -> Parser a Source #

This is like defaulted, but if the argument is the wrong type return the default instead of failing. It's mostly useful with many or many1, where you can distinguish the arguments by type.

many :: forall a. Typecheck.Typecheck a => ArgName -> Doc.Doc -> Parser [a] Source #

Collect the rest of the arguments.

many specialized to Vals, to avoid a type annotation.

many1 :: forall a. Typecheck.Typecheck a => ArgName -> Doc.Doc -> Parser (NonEmpty a) Source #

Collect the rest of the arguments, but there must be at least one.

many_pairs :: forall a b. (Typecheck.Typecheck a, Typecheck.Typecheck b) => ArgName -> Doc.Doc -> Parser [(a, b)] Source #

Collect the rest of the arguments, but expect a even number of them and pair them up.

many1_pairs :: forall a b. (Typecheck.Typecheck a, Typecheck.Typecheck b) => ArgName -> Doc.Doc -> Parser (NonEmpty (a, b)) Source #

Like many_pairs, but require at least one pair.

Require one Val for each ArgDoc given, but otherwise do no typechecking.

## defaults

This configures how an argument looks for a default in the environ.

Constructors

 None Don't default from environ at all. Prefixed Look for callname-argname. Unprefixed Look for argname. This is useful for generic parameters that should configure many calls simultaneously. Both First look for a prefixed key, then for an unprefixed one.

Instances

 # Methods # Methods # MethodsshowList :: [EnvironDefault] -> ShowS #

The argument's value is taken from the given signal, with the given default. If the value isn't given, the default is Untyped.

Like control, but the default can have a type.

Pitch signal. There's no default because that would depend on the scale.

# call

call :: Taggable y => Parser a -> (a -> Generator y d) -> WithArgDoc (Generator y d) Source #

call0 :: Taggable y => Generator y d -> WithArgDoc (Generator y d) Source #

Specialization of call for 0 arguments.

callt :: Taggable y => Parser a -> (a -> Transformer y d) -> WithArgDoc (Transformer y d) Source #

call0t :: Taggable y => Transformer y d -> WithArgDoc (Transformer y d) Source #

Specialization of callt for 0 arguments.