2 Star 0 Fork 0

mirrors_sfackler/syntax-ext-talk

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
index.html 11.33 KB
一键复制 编辑 原始数据 按行查看 历史
Steven Fackler 提交于 2014-02-25 12:00 . Small reorder
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Procedural Macros in Rust</title>
<meta name="description" content="An overview of the procedural macro system in Rust">
<meta name="author" content="Steven Fackler">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="css/reveal.min.css">
<link rel="stylesheet" href="css/theme/default.css" id="theme">
<!-- For syntax highlighting -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- If the query includes 'print-pdf', use the PDF print sheet -->
<script>
document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h1>Macros in Rust</h1>
<p>
<small>Steven Fackler / <a href="https://github.com/sfackler">sfackler</a></small>
</p>
</section>
<section>
<h2>Overview</h2>
<ul>
<li>What's a macro?</li>
<li>Why use macros?</li>
<li>What's this externally loadable thing?</li>
<li>How does it work?</li>
</ul>
</section>
<section>
<section>
<h2>What's a macro?</h2>
<p>
This stuff:
</p>
<pre><code data-trim>
let count = try!(r.read(buf));
let foo = bytes!("hello");
include_file!("some_file.rs");
println!("Hello, {}", "world");
#[deriving(Show, Eq)]
struct Foo {
i: int
}
</code></pre>
</section>
<section>
<h2>Not quite like C macros</h2>
<p>
C's preprocessor operates on a lexical level.
</p>
<p>
Think find and replace - like <code>sed</code>.
</p>
<pre><code data-trim>
#define MIN(a, b) (((a) &lt; (b)) ? (a) : (b))
#define struct union
#define DO_A_THING(t) do { \
do_blah(t); \
do_foo(t); \
} while(0)
</code></pre>
</section>
<section>
<h2>Rust's macros operate on the AST</h2>
<blockquote cite="http://en.wikipedia.org/wiki/Abstract_syntax_tree">
&ldquo;An abstract syntax tree (AST), or just
syntax tree, is a tree representation of the
abstract syntactic structure of source code written
in a programming language.&rdquo;
</blockquote>
<pre><code data-trim>
pub enum Expr_ {
ExprCall(@Expr, ~[@Expr]),
ExprMatch(@Expr, ~[Arm]),
ExprForLoop(@Pat, @Expr, P&lt;Block&gt;, Option&lt;Ident&gt;),
...
}
pub enum Item_ {
ItemFn(P&lt;FnDecl&gt;, Purity, AbiSet, Generics, P&lt;Block&gt;),
ItemTrait(Generics, ~[TraitDef], ~[TraitMethod]),
...
}
...
</code></pre>
</section>
</section>
<section>
<section>
<h2>Why?</h2>
<p>
Macros can do things that normal code simply can't.
</p>
</section>
<section>
<h2>Why?</h2>
<p>Return from the invoking function</p>
<pre><code data-trim>
macro_rules! try(
($e:expr) =&gt; (
match $e {
Ok(e) =&gt; e,
Err(e) =&gt; return Err(e)
}
)
)
fn read_foo(r: &amp;mut Reader) -&gt; Result&lt;Foo, IoError&gt; {
let bar = try!(r.read_be_i32());
let baz = try!(r.read_bytes(10));
Ok(Foo { bar: bar, baz: baz })
}
</code></pre>
</section>
<section>
<h2>Why?</h2>
<p>(Almost) freeform syntax</p>
<pre><code data-trim>
let map = make_map!(Start with collections::HashMap::new() and add
"foo" =&gt; 1,
"bar" =&gt; 2,
"baz" =&gt; 3);
</code></pre>
</section>
<section>
<h2>Why?</h2>
<p>Do work at compile time instead of run time!</p>
<pre><code data-trim>
test.rs:2:35: 2:37 error: argument never used
test.rs:2 println!("hello {}", "world", 10);
^~
</code></pre>
</section>
</section>
<section>
<section>
<h2>How does it work?</h2>
<p>
Syntax extensions don't have to be defined in the
compiler anymore! (<a href="https://github.com/mozilla/rust/issues/11151">#11151</a>)
</p>
<p>
They can be implemented in libraries that the
compiler can load into itself.
</p>
</section>
<section>
<h2>Basic idea</h2>
<p>
It's simple for <code>macro_rules!</code>.
</p>
<pre><code data-trim>
#[macro_export]
macro_rules! my_macro(() =&gt; (1))
</code></pre>
</section>
<section>
<h2>Basic idea</h2>
<p>
It's a bit more complicated for procedural macros.
Libraries define a <code>macro_registrar</code>
function to register procedural macros with the
compiler.
</p>
<pre><code data-trim>
#[macro_registrar]
pub fn registrar(cb: |ast::Name, ext::base::SyntaxExtension|) {
...
}
</code></pre>
<pre><code data-trim>
pub enum SyntaxExtension {
// e.g. #[deriving(...)]
ItemDecorator(...),
// e.g. try!(...)
NormalTT(...),
// e.g. macro_rules! foo(...)
IdentTT(...),
}
</code></pre>
</section>
<section>
<h2>Basic idea</h2>
<p>
Client code annotates the crate import to tell the
compiler to load syntax extensions from it.
</p>
<pre><code data-trim>
#[feature(phase)];
#[phase(syntax)]
extern crate my_macros;
fn main() {
let _x = my_macro!();
}
</code></pre>
</section>
<section>
<h2>Example!</h2>
<p>
Let's write a syntax extension that creates sorted
arrays of strings:
</p>
<pre><code data-trim>
#[feature(phase)];
#[phase(syntax)]
extern crate sort;
fn main() {
assert_eq!(sort!("z", "", "hello", "a"),
["", "a", "hello", "z"]);
}
</code></pre>
</section>
<section>
<h2>Example!</h2>
<a href="https://github.com/sfackler/syntax-ext-talk/tree/gh-pages/simple-ext">Source here</a>
</section>
</section>
<section>
<h2>Caveats</h2>
<ul>
<li>
Working with the AST can be extraordinarily verbose
- try creating an <code>impl</code> block via AST
nodes (or don't).
</li>
<li>
No type information.
</li>
<li>
Namespacing can be tricky. There's no way of
knowing what path a certain item is accessible by.
</li>
</ul>
</section>
<section>
<h2>&#9888; Warning! &#9888;</h2>
<p>
External syntax extensions are feature gated for a
reason! The API can and will change.
</p>
</section>
<section>
<h2>Questions?</h2>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
// Parallax scrolling
// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',
// parallaxBackgroundSize: '2100px 900px',
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});
</script>
</body>
</html>
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors_sfackler/syntax-ext-talk.git
[email protected]:mirrors_sfackler/syntax-ext-talk.git
mirrors_sfackler
syntax-ext-talk
syntax-ext-talk
gh-pages

搜索帮助