diff --git a/deps.tex b/deps.tex
index 3ced583..2a99206 100644
--- a/deps.tex
+++ b/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,8 +74,9 @@ component TodoMVC {
}
view {
-
+
[for (key, line) in {todos} : List]
- {line}
@@ -74,6 +84,21 @@ component TodoMVC {
}
}
- \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}
\ No newline at end of file
diff --git a/dot/component_backend.dot b/dot/component_backend.dot
new file mode 100644
index 0000000..1cce7b2
--- /dev/null
+++ b/dot/component_backend.dot
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/dot/component_backend.dot.pdf b/dot/component_backend.dot.pdf
new file mode 100644
index 0000000..8f37676
Binary files /dev/null and b/dot/component_backend.dot.pdf differ
diff --git a/dot/helloworld.dot b/dot/helloworld.dot
index 976f861..19257ee 100644
--- a/dot/helloworld.dot
+++ b/dot/helloworld.dot
@@ -3,5 +3,6 @@ digraph {
1 [label="ModelValue(\"name\")"]
2 [label="RsxSpan(\"sym_2\")"]
0 -> 1
+ 1 -> 0
1 -> 2
}
diff --git a/dot/helloworld.dot.pdf b/dot/helloworld.dot.pdf
new file mode 100644
index 0000000..b9287fe
Binary files /dev/null and b/dot/helloworld.dot.pdf differ
diff --git a/dot/todomvc.dot b/dot/todomvc.dot
index 54f5f8d..5e57182 100644
--- a/dot/todomvc.dot
+++ b/dot/todomvc.dot
@@ -1,13 +1,20 @@
digraph {
rankdir = "LR";
- 0 [label="RsxAttr(\"sym_0\", \"value\")"]
+ subgraph {
+ rank = "source";
+ 0 [label="RsxAttr(\"sym_0\", \"value\")"]
+ 2 [label="CodeSeg(\"sym_3\")"]
+ }
1 [label="ModelValue(Leaf(\"value\"))"]
- 2 [label="CodeSeg(\"sym_3\")"]
3 [label="ModelValue(Leaf(\"todos\"))"]
4 [label="RsxEvent(\"sym_0\", \"submit\")"]
- 5 [label="CodeSeg(\"sym_9\")"]
- 6 [label="Iterator(\"sym_8\")"]
+ 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
}
diff --git a/dot/todomvc.dot.pdf b/dot/todomvc.dot.pdf
new file mode 100644
index 0000000..a7bef76
Binary files /dev/null and b/dot/todomvc.dot.pdf differ
diff --git a/general.tex b/general.tex
new file mode 100644
index 0000000..fb40484
--- /dev/null
+++ b/general.tex
@@ -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;
+}
+fn for_each(mut iter: I, func: F)
+ where I: Iterator- , 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 {
+ 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 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}
+
diff --git a/main.tex b/main.tex
index d67dd24..dcb4e4f 100644
--- a/main.tex
+++ b/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}
diff --git a/parsing.tex b/parsing.tex
index e0a1464..cc72d07 100644
--- a/parsing.tex
+++ b/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,
+}
+
+enum Rsx {
+ Elem(Elem),
+ Code(Context, Expr),
+ Text(String),
+ ForLoop(Pat, Expr, Type, Vec),
+}
+
+...
+ \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}
\ No newline at end of file
diff --git a/todomvc.png b/todomvc.png
new file mode 100644
index 0000000..bcba4d0
Binary files /dev/null and b/todomvc.png differ
diff --git a/watch.sh b/watch.sh
index 3792e4b..78e89b5 100755
--- a/watch.sh
+++ b/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
\ No newline at end of file