updates
This commit is contained in:
parent
dd0674a798
commit
d8199f9cbb
12 changed files with 339 additions and 41 deletions
59
deps.tex
59
deps.tex
|
@ -1,12 +1,12 @@
|
|||
\begin{frame}[fragile]
|
||||
\frametitle{Deep Dive into Dependency Calculation}
|
||||
\frametitle{Deep dive into dependency calculation}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{0.55\textwidth}
|
||||
\begin{verbatim}
|
||||
\begin{column}{0.5\textwidth}
|
||||
\begin{Verbatim}[fontsize=\small]
|
||||
component HelloWorld {
|
||||
model {
|
||||
name: String = "hello",
|
||||
name: String = "",
|
||||
}
|
||||
|
||||
view {
|
||||
|
@ -14,7 +14,7 @@ component HelloWorld {
|
|||
"Hello, " {name} "!"
|
||||
}
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{Verbatim}
|
||||
\end{column}
|
||||
\begin{column}{0.3\textwidth}
|
||||
Points of interest:
|
||||
|
@ -28,36 +28,45 @@ component HelloWorld {
|
|||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Generated Dependency Chart}
|
||||
\frametitle{Generated dependency chart}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=0.6\textwidth]{{helloworld.dot}.png}
|
||||
\includegraphics[width=0.6\textwidth]{{./dot/helloworld.dot}.pdf}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Generated Dependency Chart}
|
||||
\frametitle{Generated dependency chart}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\includegraphics[width=\textwidth]{{helloworld.dot}.png}
|
||||
\includegraphics[width=\textwidth]{{./dot/helloworld.dot}.pdf}
|
||||
\end{column}
|
||||
\begin{column}{0.5\textwidth}
|
||||
\begin{itemize}
|
||||
\item All possible dependent actors are uniquely identified.
|
||||
\begin{itemize}[<+>]
|
||||
\item Symbolizes all interactions within the application.
|
||||
\item All possible dependent actors are uniquely identified.
|
||||
\item Simple DFS will tell us all updates that need to occur.
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Case Study 2: Dependencies of TodoMVC}
|
||||
\begin{frame}
|
||||
\frametitle{Case study 2: TodoMVC}
|
||||
|
||||
\includegraphics[width=\textwidth]{{todomvc.dot}.png}
|
||||
\begin{center}
|
||||
\begin{Verbatim}[fontsize=\tiny]
|
||||
\includegraphics[width=0.7\textwidth]{./todomvc.png}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Case study 2: dependencies of TodoMVC}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=0.85\textwidth]{{./dot/todomvc.dot}.pdf}
|
||||
|
||||
\begin{BVerbatim}[fontsize=\tiny]
|
||||
component TodoMVC {
|
||||
model {
|
||||
value: String = "",
|
||||
|
@ -65,7 +74,8 @@ component TodoMVC {
|
|||
}
|
||||
|
||||
view {
|
||||
<input bind:value="value" on:submit={|o@todos, o@value| { set!(todos = todos.with(value));
|
||||
<input bind:value="value"
|
||||
on:submit={|o@todos, o@value| { set!(todos = todos.with(value));
|
||||
set!(value = ""); }} />
|
||||
<ul>
|
||||
[for (key, line) in {todos} : List<String>]
|
||||
|
@ -74,6 +84,21 @@ component TodoMVC {
|
|||
</ul>
|
||||
}
|
||||
}
|
||||
\end{Verbatim}
|
||||
\end{BVerbatim}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Challenges with TodoMVC}
|
||||
|
||||
\begin{itemize}
|
||||
\item Everything within iterator must be parameterized.
|
||||
\begin{itemize}
|
||||
\item Generated code must be parameterized as well.
|
||||
\end{itemize}
|
||||
\item "Reconciliation", or re-updating the model on change.
|
||||
\begin{itemize}
|
||||
\item Consider hash-map-backed linked list implementations.
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{frame}
|
32
dot/component_backend.dot
Normal file
32
dot/component_backend.dot
Normal file
|
@ -0,0 +1,32 @@
|
|||
digraph {
|
||||
subgraph {
|
||||
backend [label = "trait Backend"]
|
||||
web [label = "struct Web;"]
|
||||
native [label = "struct Native;"]
|
||||
|
||||
web_back_impl [label = "impl Backend for Web", shape="rectangle"]
|
||||
native_back_impl [label = "impl Backend for Native", shape="rectangle"]
|
||||
|
||||
web -> web_back_impl
|
||||
web_back_impl -> backend
|
||||
|
||||
native -> native_back_impl
|
||||
native_back_impl -> backend
|
||||
|
||||
ib_trait [label = "trait InputBoxTrait { type Backend; }"]
|
||||
ib_web [label = "struct InputBoxWeb {\l web_ref: Reference,\l}\l"]
|
||||
ib_native [label = "struct InputBoxNative {\l gl_ctx: GlContext,\l}\l"]
|
||||
|
||||
ib_web_trait_impl [label = "impl InputBoxTrait for InputBoxWeb {\l type Backend = Web;\l}\l", shape="rectangle"]
|
||||
ib_native_trait_impl [label = "impl InputBoxTrait for InputBoxNative {\l type Backend = Native;\l}\l", shape="rectangle"]
|
||||
|
||||
ib_web_trait_impl -> ib_trait
|
||||
ib_native_trait_impl -> ib_trait
|
||||
|
||||
ib_web -> ib_web_trait_impl
|
||||
ib_web_trait_impl -> web
|
||||
|
||||
ib_native -> ib_native_trait_impl
|
||||
ib_native_trait_impl -> native
|
||||
}
|
||||
}
|
BIN
dot/component_backend.dot.pdf
Normal file
BIN
dot/component_backend.dot.pdf
Normal file
Binary file not shown.
|
@ -3,5 +3,6 @@ digraph {
|
|||
1 [label="ModelValue(\"name\")"]
|
||||
2 [label="RsxSpan(\"sym_2\")"]
|
||||
0 -> 1
|
||||
1 -> 0
|
||||
1 -> 2
|
||||
}
|
||||
|
|
BIN
dot/helloworld.dot.pdf
Normal file
BIN
dot/helloworld.dot.pdf
Normal file
Binary file not shown.
|
@ -1,13 +1,20 @@
|
|||
digraph {
|
||||
rankdir = "LR";
|
||||
|
||||
subgraph {
|
||||
rank = "source";
|
||||
0 [label="RsxAttr(\"sym_0\", \"value\")"]
|
||||
1 [label="ModelValue(Leaf(\"value\"))"]
|
||||
2 [label="CodeSeg(\"sym_3\")"]
|
||||
}
|
||||
1 [label="ModelValue(Leaf(\"value\"))"]
|
||||
3 [label="ModelValue(Leaf(\"todos\"))"]
|
||||
4 [label="RsxEvent(\"sym_0\", \"submit\")"]
|
||||
subgraph {
|
||||
rank = "same";
|
||||
5 [label="CodeSeg(\"sym_9\")"]
|
||||
6 [label="Iterator(\"sym_8\")"]
|
||||
7 [label="RsxSpan(\"sym_10\")"]
|
||||
}
|
||||
0 -> 1
|
||||
1 -> 0
|
||||
2 -> 3
|
||||
|
@ -15,4 +22,5 @@ digraph {
|
|||
4 -> 2
|
||||
5 -> 6
|
||||
3 -> 5
|
||||
6 -> 7
|
||||
}
|
||||
|
|
BIN
dot/todomvc.dot.pdf
Normal file
BIN
dot/todomvc.dot.pdf
Normal file
Binary file not shown.
167
general.tex
Normal file
167
general.tex
Normal file
|
@ -0,0 +1,167 @@
|
|||
\begin{frame}
|
||||
\frametitle{Interlude: Generalization}
|
||||
|
||||
\begin{itemize}
|
||||
\item All generated code must never refer to specific implementations.
|
||||
\item Whether or not a specific component is implemented should be determined at compile time.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Traits}
|
||||
|
||||
\begin{itemize}
|
||||
\item Traits are interfaces; describe a set of methods.
|
||||
\item Traits are constraints; they limit function input.
|
||||
\item Traits are markers; they can indicate certain properties.
|
||||
\end{itemize}
|
||||
|
||||
\begin{center}
|
||||
\begin{BVerbatim}[fontsize=\small]
|
||||
trait Iterator {
|
||||
type Item;
|
||||
fn next(&mut self) -> Option<Self::Item>;
|
||||
}
|
||||
fn for_each<I, T, F>(mut iter: I, func: F)
|
||||
where I: Iterator<Item=T>, F: Fn(T) {
|
||||
loop {
|
||||
match iter.next() {
|
||||
Some(next) => func(next),
|
||||
None => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{BVerbatim}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{How can we use traits to our advantage?}
|
||||
|
||||
\begin{itemize}
|
||||
\item Have a \texttt{Backend} trait to represent different backends
|
||||
\end{itemize}
|
||||
|
||||
\begin{center}
|
||||
\begin{BVerbatim}
|
||||
trait Backend {
|
||||
fn func1(...) -> (...);
|
||||
}
|
||||
\end{BVerbatim}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{How can we use traits to our advantage?}
|
||||
|
||||
\begin{itemize}
|
||||
\item Have a \texttt{Component} trait to represent different components
|
||||
\item \texttt{Component}s are \textit{parameterized} by backends
|
||||
\end{itemize}
|
||||
|
||||
\begin{center}
|
||||
\begin{BVerbatim}
|
||||
trait Component<B: Backend> {
|
||||
fn foo(...) -> Bar;
|
||||
}
|
||||
\end{BVerbatim}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{How can we use traits to our advantage?}
|
||||
|
||||
\begin{itemize}
|
||||
\item Individual components implement a trait on a specific backend.
|
||||
\item If there's no implementation, the compile will fail.
|
||||
\end{itemize}
|
||||
|
||||
\begin{center}
|
||||
\begin{BVerbatim}
|
||||
struct InputBox {
|
||||
some_field_1: SomeType1,
|
||||
some_field_2: SomeType2,
|
||||
}
|
||||
|
||||
// Now we can use InputBox for web targets!
|
||||
impl Component<Web> for InputBox {
|
||||
fn foo(...) -> Bar {
|
||||
(...)
|
||||
}
|
||||
}
|
||||
\end{BVerbatim}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{It's not that easy...}
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Problem:} all backends now share the same data structure.
|
||||
\item A web input box needs different data than a native one.
|
||||
\end{itemize}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\begin{Verbatim}
|
||||
struct InputBoxWeb {
|
||||
web_ref: Reference,
|
||||
}
|
||||
\end{Verbatim}
|
||||
\end{column}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\begin{Verbatim}
|
||||
struct InputBoxNative {
|
||||
gl_ctx: GlContext,
|
||||
}
|
||||
\end{Verbatim}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Don't limit components or backends}
|
||||
|
||||
We don't want to end up in a scenario where we're enumerating all backends or components. For example:
|
||||
|
||||
\vspace{1em}
|
||||
\begin{columns}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\begin{Verbatim}
|
||||
enum InputBox {
|
||||
Web(...),
|
||||
Native(...),
|
||||
...
|
||||
}
|
||||
\end{Verbatim}
|
||||
|
||||
\vspace{0.5em}
|
||||
\small{What happens when we add a new backend?}
|
||||
\end{column}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\begin{Verbatim}
|
||||
trait Backend {
|
||||
type InputBox;
|
||||
type Button;
|
||||
...
|
||||
}
|
||||
\end{Verbatim}
|
||||
|
||||
\vspace{0.5em}
|
||||
\small{What happens when we add a new component?}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Potential model}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=.85\textwidth]{{./dot/component_backend.dot}.pdf}
|
||||
\end{center}
|
||||
|
||||
\begin{itemize}
|
||||
\item \small{How do we discover the concrete implementation from the abstract trait?}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
28
main.tex
28
main.tex
|
@ -6,14 +6,12 @@
|
|||
\usepackage{graphicx}
|
||||
\usepackage{fancyvrb}
|
||||
|
||||
\graphicspath{ {./dot/} }
|
||||
|
||||
\setbeamercovered{transparent}
|
||||
|
||||
\title{enterprise}
|
||||
\subtitle{UI Framework Project}
|
||||
\author{Michael Zhang}
|
||||
\date[\today]{SIFT Interview, \today}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
|
||||
|
@ -23,7 +21,18 @@
|
|||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{High-Level Goals}
|
||||
\frametitle{What's out there today?}
|
||||
|
||||
\begin{itemize}[<+>]
|
||||
\item React: Immediate-mode style framework
|
||||
\item Elm: Functional message-passing framework
|
||||
\item Svelte: Compile-time framework
|
||||
\item Roll your own... ?
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{High-level goals}
|
||||
|
||||
\begin{itemize}[<+>]
|
||||
\item Declarative-style programming.
|
||||
|
@ -32,9 +41,6 @@
|
|||
\item No framework bloat.
|
||||
\note{enterprise is more like a compiler than a framework in the sense that the code it generates doesn't need to contain the actual compilation process.}
|
||||
|
||||
\item Ahead-of-time guarantees.
|
||||
\note{Another benefit of it being a compiler is that it is difficult to get run-time errors. If it compiles, it works.}
|
||||
|
||||
\item Separation of business logic and implementation.
|
||||
\note{Talk about Epic?}
|
||||
\end{itemize}
|
||||
|
@ -53,7 +59,7 @@
|
|||
\begin{verbatim}
|
||||
component HelloWorld {
|
||||
model {
|
||||
name: String = "hello",
|
||||
name: String = "",
|
||||
}
|
||||
|
||||
view {
|
||||
|
@ -78,10 +84,12 @@
|
|||
|
||||
\include{deps}
|
||||
|
||||
\include{general}
|
||||
|
||||
\include{codegen}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Future Work}
|
||||
\frametitle{Future work}
|
||||
|
||||
\begin{itemize}
|
||||
\item Full DSL, independent from Rust.
|
||||
|
@ -89,6 +97,8 @@
|
|||
\item Asynchronous event handlers.
|
||||
\item Eliminating unnecessary model stores.
|
||||
\item Connecting to other frameworks (GTK, Iced, etc.)
|
||||
\item Interpreted executor for fast prototyping.
|
||||
\item Backend code generation.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
|
|
73
parsing.tex
73
parsing.tex
|
@ -1,18 +1,18 @@
|
|||
\begin{frame}[fragile]
|
||||
\frametitle{Deep Dive into Parsing DSL Syntax}
|
||||
\frametitle{Deep dive into parsing DSL syntax}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{0.3\textwidth}
|
||||
\begin{itemize}
|
||||
\begin{itemize}[<+>]
|
||||
\item Hand-rolled recursive-descent parser.
|
||||
\item Why not use LR parser generator?
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{0.55\textwidth}
|
||||
\begin{verbatim}
|
||||
\begin{column}{0.5\textwidth}
|
||||
\begin{Verbatim}[fontsize=\small]
|
||||
component HelloWorld {
|
||||
model {
|
||||
name: String = "hello",
|
||||
name: String = "",
|
||||
}
|
||||
|
||||
view {
|
||||
|
@ -20,7 +20,7 @@ component HelloWorld {
|
|||
"Hello, " {name} "!"
|
||||
}
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{Verbatim}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
@ -30,15 +30,15 @@ component HelloWorld {
|
|||
|
||||
\begin{columns}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\begin{verbatim}
|
||||
\begin{Verbatim}
|
||||
// proc-macro library
|
||||
pub enum TokenTree {
|
||||
enum TokenTree {
|
||||
Group(Group),
|
||||
Ident(Ident),
|
||||
Punct(Punct),
|
||||
Literal(Literal),
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{Verbatim}
|
||||
\end{column}
|
||||
\begin{column}{0.4\textwidth}
|
||||
\begin{itemize}
|
||||
|
@ -51,3 +51,58 @@ pub enum TokenTree {
|
|||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Abstract syntax}
|
||||
|
||||
\begin{center}
|
||||
\begin{BVerbatim}[fontsize=\small]
|
||||
struct Component {
|
||||
name: String,
|
||||
model: ModelMap,
|
||||
view: Vec<Rsx>,
|
||||
}
|
||||
|
||||
enum Rsx {
|
||||
Elem(Elem<Rsx>),
|
||||
Code(Context, Expr),
|
||||
Text(String),
|
||||
ForLoop(Pat, Expr, Type, Vec<Rsx>),
|
||||
}
|
||||
|
||||
...
|
||||
\end{BVerbatim}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Checking your work.. with property testing}
|
||||
|
||||
\begin{itemize}[<+>]
|
||||
\item Define certain properties about the procedures.
|
||||
\item Define types of data that can be passed in.
|
||||
\item Create "strategies" for randomly generating complex data.
|
||||
\item Computer generates input cases based on the strategies.
|
||||
\item Bonus: input cases are "shrunk" down to the minimal case.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Property testing example}
|
||||
|
||||
\begin{Verbatim}[fontsize=\small]
|
||||
proptest! {
|
||||
#[test]
|
||||
fn tokens_parse_compatibility(tree in arbitrary_component()) {
|
||||
// turn the input tree into tokens and back
|
||||
let tokens = tree.to_token_stream();
|
||||
let mut visitor = Visitor::from_tokens(tokens.clone());
|
||||
let tree2 = visitor.next().unwrap().unwrap();
|
||||
|
||||
// compare the trees
|
||||
prop_assert_eq!(tree.name, tree2.name);
|
||||
prop_assert_eq!(tree.model, tree2.model);
|
||||
prop_assert_eq!(tree.view, tree2.view);
|
||||
}
|
||||
}
|
||||
\end{Verbatim}
|
||||
\end{frame}
|
BIN
todomvc.png
Normal file
BIN
todomvc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
2
watch.sh
2
watch.sh
|
@ -8,6 +8,6 @@ killgroup() {
|
|||
kill 0
|
||||
}
|
||||
|
||||
watchexec -w dot -e dot "dot -Tpng -O dot/*.dot" &
|
||||
watchexec -w dot -e dot "dot -Tpdf -O dot/*.dot" &
|
||||
watchexec -e tex "tectonic main.tex" &
|
||||
wait
|
Loading…
Reference in a new issue