ftd
crateftd
is the crate that implements the language.ftd_v2_interpret_helper()
in main.rs
to see how this crate is used as a standalone project.One design requirement for ftd
is to not perform IO operations. This is done
so ftd
and (soon) fastn-core
can be used in a variety of ways, like using
ftd
binding from Python, Node, Ruby, Java etc. To do this ftd
interpreter
acts as a state machine, yielding to the caller every time ftd
can not make
progress because it needs any IO operation, and lets the "host" perform the
IO operation, and whenever the result is ready, the host calls "continue" on
the interpter state machine.
let mut interpreter_state = ftd::interpreter::interpret(name, source)?;
ftd::interpreter::interpret()
returns a ftd::interpreter::Interpreter
on
success:ftd::interpreter::Interpreter
pub enum Interpreter {
StuckOnImport {
module: String,
state: InterpreterState,
caller_module: String,
},
Done {
document: Document,
},
StuckOnProcessor {
state: InterpreterState,
ast: ftd::ast::AST,
module: String,
processor: String,
caller_module: String,
},
StuckOnForeignVariable {
state: InterpreterState,
module: String,
variable: String,
caller_module: String,
},
}
If the ftd
document did not have any IO operations (no imports, no
processors, no foreign variables), then
the first call itself will return Interpreter::Done
, else the interpreter is
"stuck" on one of those.
The "host", which is currently fastn-core
, has to help ftd
by doing the
actual operation, in case of StuckOnImport
, they have to resolve the import
path, and return the document's content by calling,
Interpreter::continue_after_import()
, and passing it ParsedDocument
, which
we will look later in this document.
foreign variables
and foreign functions
, it is the job of the fastn host
to manage these, and inform
fastn
that the document contains these, so fastn
can type check things, and
yield control back to host when the foreign variables or functions are
evaluated. The list of foreign variables and functions are also passed to
Interpreter::continue_after_import()
.StuckOnProcessor
section
, you will read about them
in the P1 Parser below, and return a Value
.bag
(ftd::interpreter::InterpreterState::bag
field), of type
ftd::Map<ftd::interpreter::Thing>
. ftd::Map<T>
is an alias to
std::collections::BTreeMap<String, T>
;ftd::interpreter::Thing
pub enum Thing {
Record(ftd::interpreter::Record),
OrType(ftd::interpreter::OrType),
OrTypeWithVariant {
or_type: String,
variant: ftd::interpreter::OrTypeVariant,
},
Variable(ftd::interpreter::Variable),
Component(ftd::interpreter::ComponentDefinition),
WebComponent(ftd::interpreter::WebComponentDefinition),
Function(ftd::interpreter::Function),
}
bag
. The key in the bag is the full name of the module, and then
name of the thing, with #
as the concatenation character.fastn
code is first encountered, we use the
ftd::p1::parse()
function to parse it to ftd::p1::Section
struct:ftd::p1::Section
pub struct Section {
pub name: String,
pub kind: Option<String>,
pub caption: Option<ftd::p1::Header>,
pub headers: ftd::p1::Headers,
pub body: Option<Body>,
pub sub_sections: Vec<Section>,
pub is_commented: bool,
pub line_number: usize,
pub block_body: bool,
}
ftd-p1
grammar.