module Lang_values: sig
.. end
Values in the Liquidsoap language.
exception Parse_error of ((Lexing.position * Lexing.position) * string)
A parsing error.
val debug : bool
Are we in debugging mode?
val errors_as_warnings : bool Pervasives.ref
Should errors be considered as simple warnings?
Kinds
module T: Lang_types
val ref_t : pos:T.pos option ->
level:int -> T.t -> T.t
val zero_t : T.t
val succ_t : T.t -> T.t
val variable_t : T.t
val add_t : int -> T.t -> T.t
val type_of_int : int -> T.t
val frame_kind_t : ?pos:T.pos option ->
?level:int ->
T.t -> T.t -> T.t -> T.t
A frame kind type is a purely abstract type representing a frame kind.
The parameters audio,video,midi
are intended to be multiplicity types,
i.e. types of the form Succ*(Zero|Variable).
val of_frame_kind_t : T.t ->
(T.t, T.t, T.t) Frame.fields
val format_t : ?pos:T.pos option ->
?level:int -> T.t -> T.t
Type of audio formats that can encode frame of a given kind.
val source_t : ?active:bool ->
?pos:T.pos option ->
?level:int -> T.t -> T.t
Type of sources carrying frames of a given kind.
val of_source_t : T.t -> T.t
val request_t : ?pos:T.pos option ->
?level:int -> T.t -> T.t
val of_request_t : T.t -> T.t
val type_of_mul : pos:T.pos option ->
level:int -> Frame.multiplicity -> T.t
val type_of_format : pos:T.pos option ->
level:int -> Encoder.format -> T.t
Terms
The way we implement this mini-language is not very efficient. It should not
matter, since very little computation is done here. It is mostly used for a
single run on startup to build the sources, and then sometimes for building
transitions. Terms are small, no recursion is possible. In order to report
informative errors, including runtime errors (invalid values of a valid type
given to a FF) we need to keep a complete AST all the way long. We actually
don't need the types anymore after the static checking, but I don't want to
bother with stripping down to another datatype.
module Vars: Set.Make
(
String
)
Sets of variables.
type
term = {
}
type
let_t = {
|
doc : Doc.item * (string * string) list ; |
|
var : string ; |
|
mutable gen : (int * T.constraints) list ; |
|
def : term ; |
|
body : term ; |
}
type
in_term =
val is_ground : term -> bool
val print_term : term -> string
Print terms, (almost) assuming they are in normal form.
val free_vars : ?bound:Vars.elt list -> term -> Vars.t
val free_vars : ?bound:Vars.elt list -> term -> Vars.t
val can_ignore : T.t -> bool
val is_fun : T.t -> bool
val is_source : T.t -> bool
Check that all let-bound variables are used.
No check is performed for variable arguments.
This cannot be done at parse-time (as for the computatin of the
free variables of functions) because we need types, as well as
the ability to distinguish toplevel and inner let-in terms.
exception Unused_variable of (string * Lexing.position)
val check_unused : lib:bool -> term -> unit
val map_types : ((int * T.constraints) list -> T.t -> T.t) ->
(int * T.constraints) list ->
term -> term
Maps a function on all types occurring in a term.
Ignores variable generalizations.
val fold_types : ((int * T.constraints) list -> 'a -> T.t -> 'a) ->
(int * T.constraints) list -> 'a -> term -> 'a
Folds f
over almost all types occurring in a term,
skipping as much as possible while still
guaranteeing that f
will see all variables.
module V: sig
.. end
Values are normal forms of terms.
Built-in values and toplevel definitions
val builtins : ((int * T.constraints) list * V.value) Plug.plug
val (<:) : T.t -> T.t -> unit
val (>:) : T.t -> T.t -> unit
val value_restriction : term -> bool
exception Unbound of T.pos option * string
exception Ignored of term
val raise_ignored : term -> unit
exception No_label of term * string * bool * term
No_label (f,lbl,first,x)
indicates that the parameter x
could not be
passed to the function f
because the latter has no label lbl
.
The first
information tells whether lbl=x
is the first parameter with
label lbl
in the considered application, which makes the message a bit
more helpful.
val check : ?ignored:bool -> term -> unit
val check : ?ignored:bool -> term -> unit
Computations
exception F of string
For internal use. I want to give an ID to sources built by FFI application
based on the name under which the FFI is registered.
get_name f
returns the name under which the FFI f is registered.
val get_name : (V.full_env -> T.t -> V.value) -> string
val remove_first : ('a -> bool) -> 'a list -> 'a * 'a list
remove_first f l
removes the first element e
of l
such that f e
,
and returns e,l'
where l'
is the list without e
.
Asserts that there is such an element.
Evaluation has to be typed, because some FFI's have a behavior
that depends on their return type (for example, source and request
creations). This is annoying but we really need a type inference kind
of mechanism to obtain the information that such functions need,
so this seems like the right thing to do.
So, when we evaluate a variable of type T, we have to lookup
a let-definition, whose type has T as an instance, instantiate it
and unify it with T. But this is not enough: we need the types
inside the definition to get instantiated properly too.
This also requires to duplicate the definition before
instantiation, to avoid sharing the instantiation with
the definition itself and its future/past instantiations.
val instantiate : generalized:(int * T.constraints) list ->
V.value -> V.value
val lookup : (string * ((int * T.constraints) list * V.value))
list -> string -> T.t -> V.value
val eval : env:(Vars.elt *
((int * T.constraints) list * V.value))
list ->
term -> V.value
val apply : t:T.t ->
V.value ->
(string * V.value) list -> V.value
val toplevel_add : Doc.item * (string * string) list ->
string ->
generalized:(int * T.constraints) list ->
V.value -> unit
Add toplevel definitions to builtins
so they can be looked
during the evaluation of the next scripts.
Also try to generate a structured documentation from the source code.
val eval_toplevel : ?interactive:bool -> term -> V.value