gdritter repos rust-examples / 874c1e9
Added all files Getty Ritter 10 years ago
33 changed file(s) with 1723 addition(s) and 0 deletion(s). Collapse all Expand all
1 Rust Examples
2 =============
3
4 These are small snippets of the Rust, in varying degrees of elaborateness,
5 meant to accompany the presentation given in `presentation/rust.pdf`. I am not
6 a particularly experienced Rust programmer, so these programs may differ
7 significantly from conventional Rust style or idiom, or may be written in
8 a suboptimal way.
9
10 Right now, the examples include:
11
12 - An interpreter for the untyped lambda-calculus
13 - A regular-expression matcher
14
15 Build System
16 ------------
17
18 These programs are built using [`redo`](https://github.com/apenwarr/redo),
19 which is my preferred build system for small projects. I understand that not
20 everyone has `redo`, so I've included `do`, which is a small shell
21 implementation of `redo` that rebuilds everything rather than doing clever
22 dependency-tracking like `redo` proper. You can build any of these projects with
23
24 $ cd project-dir
25 $ ../do
26
27 and clean any of them with
28
29 $ cd project-dir
30 $ ../do clean
31
32 The only project that really _needs_ a build script is the presentation,
33 which gets built with [`pandoc`](http://johnmacfarlane.net/pandoc/) and
34 then compiled with `xelatex`, but each one has a build script in case
35 you want to poke at the commands used to build the projects.
+177
-0
do less more
1 #!/bin/sh
2 #
3 # A minimal alternative to djb redo that doesn't support incremental builds.
4 # For the full version, visit http://github.com/apenwarr/redo
5 #
6 # The author disclaims copyright to this source file and hereby places it in
7 # the public domain. (2010 12 14)
8 #
9
10 # By default, no output coloring.
11 green=""
12 bold=""
13 plain=""
14
15 if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then
16 green="$(printf '\033[32m')"
17 bold="$(printf '\033[1m')"
18 plain="$(printf '\033[m')"
19 fi
20
21 _dirsplit()
22 {
23 base=${1##*/}
24 dir=${1%$base}
25 }
26
27 dirname()
28 (
29 _dirsplit "$1"
30 dir=${dir%/}
31 echo "${dir:-.}"
32 )
33
34 _dirsplit "$0"
35 export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
36
37 DO_TOP=
38 if [ -z "$DO_BUILT" ]; then
39 DO_TOP=1
40 [ -n "$*" ] || set all # only toplevel redo has a default target
41 export DO_BUILT=$PWD/.do_built
42 : >>"$DO_BUILT"
43 echo "Removing previously built files..." >&2
44 sort -u "$DO_BUILT" | tee "$DO_BUILT.new" |
45 while read f; do printf "%s\0%s.did\0" "$f" "$f"; done |
46 xargs -0 rm -f 2>/dev/null
47 mv "$DO_BUILT.new" "$DO_BUILT"
48 DO_PATH=$DO_BUILT.dir
49 export PATH=$DO_PATH:$PATH
50 rm -rf "$DO_PATH"
51 mkdir "$DO_PATH"
52 for d in redo redo-ifchange; do
53 ln -s "$REDO" "$DO_PATH/$d";
54 done
55 [ -e /bin/true ] && TRUE=/bin/true || TRUE=/usr/bin/true
56 for d in redo-ifcreate redo-stamp redo-always; do
57 ln -s $TRUE "$DO_PATH/$d";
58 done
59 fi
60
61
62 _find_dofile_pwd()
63 {
64 dofile=default.$1.do
65 while :; do
66 dofile=default.${dofile#default.*.}
67 [ -e "$dofile" -o "$dofile" = default.do ] && break
68 done
69 ext=${dofile#default}
70 ext=${ext%.do}
71 base=${1%$ext}
72 }
73
74
75 _find_dofile()
76 {
77 local prefix=
78 while :; do
79 _find_dofile_pwd "$1"
80 [ -e "$dofile" ] && break
81 [ "$PWD" = "/" ] && break
82 target=${PWD##*/}/$target
83 tmp=${PWD##*/}/$tmp
84 prefix=${PWD##*/}/$prefix
85 cd ..
86 done
87 base=$prefix$base
88 }
89
90
91 _run_dofile()
92 {
93 export DO_DEPTH="$DO_DEPTH "
94 export REDO_TARGET=$PWD/$target
95 local line1
96 set -e
97 read line1 <"$PWD/$dofile" || true
98 cmd=${line1#"#!/"}
99 if [ "$cmd" != "$line1" ]; then
100 /$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2"
101 else
102 :; . "$PWD/$dofile" >"$tmp.tmp2"
103 fi
104 }
105
106
107 _do()
108 {
109 local dir=$1 target=$2 tmp=$3
110 if [ ! -e "$target" ] || [ -d "$target" -a ! -e "$target.did" ]; then
111 printf '%sdo %s%s%s%s\n' \
112 "$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2
113 echo "$PWD/$target" >>"$DO_BUILT"
114 dofile=$target.do
115 base=$target
116 ext=
117 [ -e "$target.do" ] || _find_dofile "$target"
118 if [ ! -e "$dofile" ]; then
119 echo "do: $target: no .do file" >&2
120 return 1
121 fi
122 [ ! -e "$DO_BUILT" ] || [ ! -d "$(dirname "$target")" ] ||
123 : >>"$target.did"
124 ( _run_dofile "$target" "$base" "$tmp.tmp" )
125 rv=$?
126 if [ $rv != 0 ]; then
127 printf "do: %s%s\n" "$DO_DEPTH" \
128 "$dir$target: got exit code $rv" >&2
129 rm -f "$tmp.tmp" "$tmp.tmp2"
130 return $rv
131 fi
132 mv "$tmp.tmp" "$target" 2>/dev/null ||
133 ! test -s "$tmp.tmp2" ||
134 mv "$tmp.tmp2" "$target" 2>/dev/null
135 rm -f "$tmp.tmp2"
136 else
137 echo "do $DO_DEPTH$target exists." >&2
138 fi
139 }
140
141
142 # Make corrections for directories that don't actually exist yet.
143 _dir_shovel()
144 {
145 local dir base
146 xdir=$1 xbase=$2 xbasetmp=$2
147 while [ ! -d "$xdir" -a -n "$xdir" ]; do
148 _dirsplit "${xdir%/}"
149 xbasetmp=${base}__$xbase
150 xdir=$dir xbase=$base/$xbase
151 echo "xbasetmp='$xbasetmp'" >&2
152 done
153 }
154
155
156 _redo()
157 {
158 set +e
159 for i in "$@"; do
160 _dirsplit "$i"
161 _dir_shovel "$dir" "$base"
162 dir=$xdir base=$xbase basetmp=$xbasetmp
163 ( cd "$dir" && _do "$dir" "$base" "$basetmp" )
164 [ "$?" = 0 ] || return 1
165 done
166 }
167
168
169 _redo "$@"
170 [ "$?" = 0 ] || exit 1
171
172 if [ -n "$DO_TOP" ]; then
173 echo "Removing stamp files..." >&2
174 [ ! -e "$DO_BUILT" ] ||
175 while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
176 xargs -0 rm -f 2>/dev/null
177 fi
1 if [ -e lcalc ]; then rm lcalc; fi
1 redo-ifchange lcalc
1 redo-ifchange lcalc.rs
2 rustc lcalc.rs -o $3
1 use std::str::eq_slice;
2
3 #[deriving(Eq,Clone)]
4 enum Term {
5 Num(int),
6 Var(~str),
7 Lam(~str, ~Term),
8 App(~Term, ~Term),
9 Let(~str, ~Term, ~Term),
10 }
11
12 #[deriving(Eq,Clone)]
13 enum Val {
14 VNum(int),
15 VLam(~str, ~Term, ~Env),
16 }
17
18 #[deriving(Eq,Clone)]
19 enum Env {
20 Empty,
21 Binding(~str, ~Val, ~Env),
22 }
23
24 fn lookup(s: &str, e: &Env) -> ~Val {
25 match *e {
26 Empty => { fail!(format!("Couldn't find {} in environment", s)) }
27 Binding(ref n, ref v, ref p) => {
28 if eq_slice(*n, s) {
29 v.clone()
30 } else {
31 lookup(s, *p)
32 }
33 }
34 }
35 }
36
37 fn eval(t: &Term, e: &Env) -> ~Val {
38 match t {
39 &Num(num) => { ~VNum(num) }
40 &Var(ref str) => { lookup(*str, e) }
41 &Lam(ref s, ref b) => { ~VLam(s.clone(), b.clone(), ~e.clone()) }
42 &App(ref f, ref x) => {
43 match (*eval(*f, e)) {
44 VLam(ref arg, ref body, ref env) => {
45 let newEnv = Binding(arg.clone(),
46 eval(*x, e),
47 env.clone());
48 eval(*body, &newEnv)
49 }
50 _ => fail!()
51 }
52 }
53 &Let(ref s, ref t, ref b) => {
54 let newEnv = Binding(s.clone(),
55 eval(*t, e),
56 ~e.clone());
57 eval(*b, &newEnv)
58 }
59 }
60 }
61
62 fn main() {
63 // (λx.λy.x)(5)(6)
64 let s1 = ~App(~App(~Lam(~"x",~Lam(~"y", ~Var(~"x"))),~Num(5)),~Num(8));
65 // let f = (λx.λy.x)(2) in f 4
66 let s2 = ~Let( ~"f",
67 ~App(~Lam(~"x",~Lam(~"y", ~Var(~"x"))),~Num(2)),
68 ~App(~Var(~"f"),~Num(4))
69 );
70 let e = Empty;
71 println!("s1: {:?}", eval(s1, &e));
72 println!("s2: {:?}", eval(s2, &e));
73 }
1 redo-ifchange rust.pdf
1 FILES="rust.tex rust.pdf"
2
3 for f in $FILES; do
4 if [ -e $f ]; then rm $f; fi
5 done
1 <?xml version="1.0" encoding="ISO-8859-1"?>
2 <!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="144px" height="144px" viewBox="19 19 106 106" style="enable-background:new 0 0 144 144;" xml:space="preserve">
5 <path d="M122.631,69.716l-4.394-2.72c-0.037-0.428-0.079-0.855-0.125-1.28l3.776-3.522c0.384-0.358,0.556-0.888,0.452-1.401 c-0.101-0.515-0.462-0.939-0.953-1.122l-4.827-1.805c-0.121-0.418-0.248-0.833-0.378-1.246l3.011-4.182 c0.307-0.425,0.37-0.978,0.17-1.463c-0.2-0.483-0.637-0.829-1.154-0.914l-5.09-0.828c-0.198-0.386-0.404-0.766-0.612-1.143 l2.139-4.695c0.219-0.478,0.174-1.034-0.118-1.468c-0.291-0.436-0.784-0.691-1.31-0.671l-5.166,0.18 c-0.267-0.334-0.539-0.665-0.816-0.99l1.187-5.032c0.12-0.511-0.031-1.046-0.403-1.417c-0.369-0.37-0.905-0.523-1.416-0.403 l-5.031,1.186c-0.326-0.276-0.657-0.549-0.992-0.816l0.181-5.166c0.02-0.523-0.235-1.02-0.671-1.31 c-0.437-0.292-0.99-0.336-1.467-0.119l-4.694,2.14c-0.379-0.208-0.759-0.414-1.143-0.613l-0.83-5.091 c-0.084-0.516-0.43-0.954-0.914-1.154c-0.483-0.201-1.037-0.136-1.462,0.17l-4.185,3.011c-0.412-0.131-0.826-0.257-1.244-0.377 l-1.805-4.828c-0.183-0.492-0.607-0.853-1.122-0.955c-0.514-0.101-1.043,0.07-1.4,0.452l-3.522,3.779 c-0.425-0.047-0.853-0.09-1.28-0.125l-2.72-4.395c-0.275-0.445-0.762-0.716-1.286-0.716s-1.011,0.271-1.285,0.716l-2.72,4.395 c-0.428,0.035-0.856,0.078-1.281,0.125l-3.523-3.779c-0.357-0.382-0.887-0.553-1.4-0.452c-0.515,0.103-0.939,0.463-1.122,0.955 l-1.805,4.828c-0.418,0.12-0.832,0.247-1.245,0.377l-4.184-3.011c-0.425-0.307-0.979-0.372-1.463-0.17 c-0.483,0.2-0.83,0.638-0.914,1.154l-0.83,5.091c-0.384,0.199-0.764,0.404-1.143,0.613l-4.694-2.14 c-0.477-0.218-1.033-0.173-1.467,0.119c-0.436,0.29-0.691,0.787-0.671,1.31l0.18,5.166c-0.334,0.267-0.665,0.54-0.992,0.816 l-5.031-1.186c-0.511-0.119-1.047,0.033-1.417,0.403c-0.372,0.371-0.523,0.906-0.403,1.417l1.185,5.032 c-0.275,0.326-0.547,0.656-0.814,0.99l-5.166-0.18c-0.521-0.015-1.019,0.235-1.31,0.671c-0.292,0.434-0.336,0.99-0.119,1.468 l2.14,4.695c-0.208,0.377-0.414,0.757-0.613,1.143l-5.09,0.828c-0.517,0.084-0.953,0.43-1.154,0.914 c-0.2,0.485-0.135,1.038,0.17,1.463l3.011,4.182c-0.131,0.413-0.258,0.828-0.378,1.246l-4.828,1.805 c-0.49,0.183-0.851,0.607-0.953,1.122c-0.102,0.514,0.069,1.043,0.452,1.401l3.777,3.522c-0.047,0.425-0.089,0.853-0.125,1.28 l-4.394,2.72c-0.445,0.275-0.716,0.761-0.716,1.286s0.271,1.011,0.716,1.285l4.394,2.72c0.036,0.428,0.078,0.855,0.125,1.28 l-3.777,3.523c-0.383,0.357-0.554,0.887-0.452,1.4c0.102,0.515,0.463,0.938,0.953,1.122l4.828,1.805 c0.12,0.418,0.247,0.833,0.378,1.246l-3.011,4.183c-0.306,0.426-0.371,0.979-0.17,1.462c0.201,0.485,0.638,0.831,1.155,0.914 l5.089,0.828c0.199,0.386,0.403,0.766,0.613,1.145l-2.14,4.693c-0.218,0.477-0.173,1.032,0.119,1.468 c0.292,0.437,0.789,0.692,1.31,0.671l5.164-0.181c0.269,0.336,0.54,0.665,0.816,0.992l-1.185,5.033 c-0.12,0.51,0.031,1.043,0.403,1.414c0.369,0.373,0.906,0.522,1.417,0.402l5.031-1.185c0.327,0.278,0.658,0.548,0.992,0.814 l-0.18,5.167c-0.02,0.523,0.235,1.019,0.671,1.311c0.434,0.291,0.99,0.335,1.467,0.117l4.694-2.139 c0.378,0.21,0.758,0.414,1.143,0.613l0.83,5.088c0.084,0.518,0.43,0.956,0.914,1.155c0.483,0.201,1.038,0.136,1.463-0.169 l4.182-3.013c0.413,0.131,0.828,0.259,1.246,0.379l1.805,4.826c0.183,0.49,0.607,0.853,1.122,0.953 c0.514,0.104,1.043-0.068,1.4-0.452l3.523-3.777c0.425,0.049,0.853,0.09,1.281,0.128l2.72,4.394 c0.274,0.443,0.761,0.716,1.285,0.716s1.011-0.272,1.286-0.716l2.72-4.394c0.428-0.038,0.855-0.079,1.28-0.128l3.522,3.777 c0.357,0.384,0.887,0.556,1.4,0.452c0.515-0.101,0.939-0.463,1.122-0.953l1.805-4.826c0.418-0.12,0.833-0.248,1.246-0.379 l4.183,3.013c0.425,0.305,0.979,0.37,1.462,0.169c0.484-0.199,0.83-0.638,0.914-1.155l0.83-5.088 c0.384-0.199,0.764-0.406,1.143-0.613l4.694,2.139c0.477,0.218,1.032,0.174,1.467-0.117c0.436-0.292,0.69-0.787,0.671-1.311 l-0.18-5.167c0.334-0.267,0.665-0.536,0.991-0.814l5.031,1.185c0.511,0.12,1.047-0.029,1.416-0.402 c0.372-0.371,0.523-0.904,0.403-1.414l-1.185-5.033c0.276-0.327,0.548-0.656,0.814-0.992l5.166,0.181 c0.521,0.021,1.019-0.234,1.31-0.671c0.292-0.436,0.337-0.991,0.118-1.468l-2.139-4.693c0.209-0.379,0.414-0.759,0.612-1.145 l5.09-0.828c0.518-0.083,0.954-0.429,1.154-0.914c0.2-0.483,0.137-1.036-0.17-1.462l-3.011-4.183 c0.13-0.413,0.257-0.828,0.378-1.246l4.827-1.805c0.491-0.184,0.853-0.607,0.953-1.122c0.104-0.514-0.068-1.043-0.452-1.4 l-3.776-3.523c0.046-0.425,0.088-0.853,0.125-1.28l4.394-2.72c0.445-0.274,0.716-0.761,0.716-1.285S123.076,69.991,122.631,69.716z M93.222,106.167c-1.678-0.362-2.745-2.016-2.385-3.699c0.359-1.681,2.012-2.751,3.689-2.389c1.678,0.359,2.747,2.016,2.387,3.696 S94.899,106.526,93.222,106.167z M91.729,96.069c-1.531-0.328-3.037,0.646-3.365,2.18l-1.56,7.28 c-4.814,2.185-10.16,3.399-15.79,3.399c-5.759,0-11.221-1.274-16.121-3.552l-1.559-7.28c-0.328-1.532-1.834-2.508-3.364-2.179 l-6.427,1.38c-1.193-1.228-2.303-2.536-3.323-3.917h31.272c0.354,0,0.59-0.064,0.59-0.386V81.932c0-0.322-0.236-0.386-0.59-0.386 h-9.146v-7.012h9.892c0.903,0,4.828,0.258,6.083,5.275c0.393,1.543,1.256,6.562,1.846,8.169c0.588,1.802,2.982,5.402,5.533,5.402 h15.583c0.177,0,0.366-0.02,0.565-0.056c-1.081,1.469-2.267,2.859-3.544,4.158L91.729,96.069z M48.477,106.015 c-1.678,0.362-3.33-0.708-3.691-2.389c-0.359-1.684,0.708-3.337,2.386-3.699c1.678-0.359,3.331,0.711,3.691,2.392 C51.222,103.999,50.154,105.655,48.477,106.015z M36.614,57.91c0.696,1.571-0.012,3.412-1.581,4.107 c-1.569,0.697-3.405-0.012-4.101-1.584c-0.696-1.572,0.012-3.41,1.581-4.107C34.083,55.63,35.918,56.338,36.614,57.91z M32.968,66.553l6.695-2.975c1.43-0.635,2.076-2.311,1.441-3.744l-1.379-3.118h5.423V81.16H34.207 c-0.949-3.336-1.458-6.857-1.458-10.496C32.749,69.275,32.824,67.902,32.968,66.553z M62.348,64.179v-7.205h12.914 c0.667,0,4.71,0.771,4.71,3.794c0,2.51-3.101,3.41-5.651,3.41H62.348z M109.28,70.664c0,0.956-0.035,1.902-0.105,2.841h-3.926 c-0.393,0-0.551,0.258-0.551,0.643v1.803c0,4.244-2.393,5.167-4.49,5.402c-1.997,0.225-4.211-0.836-4.484-2.058 c-1.178-6.626-3.141-8.041-6.241-10.486c3.847-2.443,7.85-6.047,7.85-10.871c0-5.209-3.571-8.49-6.005-10.099 c-3.415-2.251-7.196-2.702-8.216-2.702H42.509c5.506-6.145,12.968-10.498,21.408-12.082l4.786,5.021 c1.082,1.133,2.874,1.175,4.006,0.092l5.355-5.122c11.221,2.089,20.721,9.074,26.196,18.657l-3.666,8.28 c-0.633,1.433,0.013,3.109,1.442,3.744l7.058,3.135C109.216,68.115,109.28,69.381,109.28,70.664z M68.705,28.784 c1.24-1.188,3.207-1.141,4.394,0.101c1.185,1.245,1.14,3.214-0.103,4.401c-1.24,1.188-3.207,1.142-4.394-0.102 C67.418,31.941,67.463,29.972,68.705,28.784z M105.085,58.061c0.695-1.571,2.531-2.28,4.1-1.583 c1.569,0.696,2.277,2.536,1.581,4.107c-0.695,1.572-2.531,2.281-4.101,1.584C105.098,61.473,104.39,59.634,105.085,58.061z"/>
6 </svg>
1 % The Rust Programming Language
2 % G.D. Ritter
3 % March 2014
4
5 # The Rust Programming Language
6
7 ![](imgs/rust-logo.png)
8
9 A new systems programming language being developed by Mozilla Research, with
10 an emphasis on correctness while still allowing for very low-level programing
11 by emphasizing _zero-cost abstractions_.
12
13 # Low-Level Programming
14
15 # Low-Level Programming
16
17 \begin{center}
18 \includegraphics[width=.9\textwidth]{imgs/kanye-water-bottle-01.png}
19 \end{center}
20
21 # Low-Level Programming
22
23 \begin{center}
24 \includegraphics[width=.9\textwidth]{imgs/kanye-water-bottle-02.png}
25 \end{center}
26
27 # Systems Programming Languages
28
29 > System software is computer software designed to operate and control the
30 > computer hardware and to provide a platform for running application
31 > software, and includes such things as operating systems, utility software,
32 > device drivers, compilers, and linkers.
33 >
34 > —Wikipedia
35
36 > "Systems programs" means "programs where the constant factors are important".
37 >
38 > —Comment by `neelk` on Lambda the Ultimate
39
40 # Systems Programming Languages
41
42 ## Example Program
43
44 ~~~~{.haskell}
45 data Point = { x, y : Int }
46
47 addPoint : Point -> Point -> Point
48 addPoint p1 p2 = { x = p1.x + p2.x, y = p1.y + p2.y }
49
50 main : ()
51 main = { let a = { x = 1, y = 2 }
52 ; let b = malloc { x = 4, y = 3}
53 ; print (addPoint a (deref b))
54 ; free(b)
55 }
56 ~~~~
57
58 # Systems Programming Languages
59
60 ## C
61
62 ~~~~{.c}
63 typedef struct { int x, y; } point;
64
65 point add(point a, point b) {
66 point result = { a.x + b.x, a.y + b.y };
67 return result;
68 }
69
70 void main(int argc, char* argv[]) {
71 point a = { 1, 2 };
72 point* b = malloc(sizeof(point));
73 b->x = 4; b->y = 3;
74 point c = add(a, *b);
75 printf("{.x = %d, .y = %d}\n", c.x, c.y);
76 free(b);
77 }
78 ~~~~
79
80 # Systems Programming Languages
81
82 ## C++
83
84 ~~~~{.cpp}
85 struct point {
86 int x, y;
87 point(int _x, int _y) { x = _x; y = _y; }
88 point add(point other) {
89 return point(x + other.x, y + other.y);
90 }
91 };
92 int main(int argc, char* argv[]) {
93 point a(1, 2);
94 point* b = new point(4, 3);
95 point c = a.add(*b);
96 std::cout << "{ .x = " << c.x;
97 std::cout << ", .y = " << c.y << " }" << std::endl;
98 delete b;
99 }
100 ~~~~
101
102 # Systems Programming Languages
103
104 ## Go
105
106 ~~~~{.go}
107 type Point struct { X, Y int }
108
109 func (a Point) add(b Point) Point {
110 return Point{ a.X + b.X, a.Y + b.Y }
111 }
112
113 func main() {
114 a := Point{1, 2}
115 b := new(Point)
116 b.X, b.Y = 4, 3
117 fmt.Println(a.add(*b))
118 // No free, because Go is garbage-collected
119 }
120 ~~~~
121
122 # Systems Programming Languages
123
124 ## D
125
126 ~~~~{.d}
127 struct Point {
128 int x, y;
129 Point add(Point other) {
130 return Point(this.x + other.x, this.y + other.y);
131 }
132 }
133
134 void main() {
135 Point a = Point(1, 2);
136 Point* b = cast(Point*)GC.malloc(Point.sizeof);
137 b.x = 4; b.y = 3;
138 writeln(a.add(*b));
139 GC.free(b);
140 }
141 ~~~~
142
143 # Systems Programming Languages
144
145 ## Nimrod
146
147 ~~~~
148 type Point = tuple[x: int, y: int]
149
150 proc add(a: Point, b: Point): Point =
151 (x: a.x + b.x, y: a.y + b.y)
152
153 var a : Point
154 var b : ptr Point
155
156 a = (x: 1, y: 2)
157 b = cast[ptr Point](alloc(sizeof(Point)))
158 b.x = 4
159 b.y = 3
160 echo(add(a, b[]))
161 dealloc(b)
162 ~~~~
163
164 # Systems Programming Languages
165
166 ## Rust
167
168 ~~~~{.rust}
169 struct Point { x: int, y: int }
170
171 impl Point {
172 fn add(self, other: Point) -> Point {
173 Point { x: self.x + other.x,
174 y: self.y + other.y }
175 }
176 }
177
178 fn main() {
179 let a = Point { x: 1, y: 2 };
180 let b = ~Point { x: 4, y: 3 };
181 println!("{:?}", a.add(*b));
182 }
183 ~~~~
184
185 # Basics of Rust
186
187 # Basics of Rust
188
189 > It's like C++ grew up, went to grad school, started dating Haskell, and
190 > is sharing an office with Erlang...
191 >
192 > —Michael Sullivan
193
194 # Basics of Rust
195
196 ## Recursive Factorial
197
198 ~~~~{.rust}
199 fn fact1(n: int) -> int {
200 if n <= 0 {
201 1
202 } else {
203 n * fact1(n-1)
204 }
205 }
206 ~~~~
207
208 ## Another Recursive Factorial
209
210 ~~~~{.rust}
211 fn fact2(n: int) -> int {
212 match n {
213 0 => { 1 }
214 _ => { n * fact2(n-1) }
215 }
216 }
217 ~~~~
218
219 # Basics of Rust
220
221 ## An Imperative Factorial
222
223 ~~~~{.rust}
224 fn fact3(mut n: int) -> int {
225 let mut res = 1;
226 while (n > 0) {
227 res *= n;
228 n -= 1;
229 }
230 res
231 }
232 ~~~~
233
234 ## One More Imperative Factorial
235
236 ~~~~{.rust}
237 fn fact4(mut n: int) -> int {
238 for i in range(1, n) { n *= i; }
239 return n;
240 }
241 ~~~~
242
243 # Basics of Rust
244
245 ## Tuples
246
247 ~~~~{.rust}
248 {
249 let t: (int, int, int) = (1,2,3);
250 let (a,b,c) = t;
251 let r = match t { (a,b,c) => a + b + c };
252 }
253 ~~~~
254
255 ## Tuple Structs (i.e. named tuples)
256
257 ~~~~{.rust}
258 struct T(bool, int);
259 fn f(t: T) -> int {
260 let T(myBool, myInt) = t;
261 return if myBool { myInt } else { -myInt };
262 }
263 ~~~~
264
265 # Basics of Rust
266
267 ## Structs
268
269 ~~~~{.rust}
270 struct Point { x: f64, y: f64 }
271
272 fn isOrigin1 (p: Point) -> bool {
273 p.x == 0.0 && p.y == 0.0
274 }
275 ~~~~
276
277 ~~~~{.rust}
278 fn isOrigin2 (p: Point) -> bool {
279 match p {
280 Point { x: 0.0, y: 0.0 } => true,
281 _ => false
282 }
283 }
284 ~~~~
285
286 # Basics of Rust
287
288 ## Enums
289
290 ~~~~{.rust}
291 enum Color { Red, Green, Blue }
292
293 enum Shape {
294 Circle(Point, f64),
295 Rectangle(Point, Point),
296 }
297
298 fn area(s: Shape) -> f64 {
299 match s {
300 Circle(_, sz) => f64::consts::pi * sz * sz,
301 Rectangle(p1, p2) => (p2.x - p1.x) * (p2.y - p1.y)
302 }
303 }
304 ~~~~
305
306 # Pointers and Memory
307
308 # Pointers and Memory
309
310 \begin{center}
311 \includegraphics[width=.9\textwidth]{imgs/dawkins-owned.png}
312 \end{center}
313
314 # Pointers and Memory
315
316 ## "Owned" Pointers
317
318 ~~~~{.rust}
319 fn main() {
320 let x: ~[int] = ~[1,2,3];
321 /* x in scope */
322 {
323 let y: ~[int] = ~[4,5,6];
324 /* x, y in scope */
325 }
326 /* x in scope */
327 }
328 ~~~~
329
330 # Pointers and Memory
331
332 ## "Owned" Pointers
333
334 ~~~~{.rust}
335 fn main() {
336 let x: ~[int] = ~[1,2,3]; // malloc |----+
337 /* ... */ // |
338 { // |
339 let y: ~[int] = ~[4,5,6]; // malloc |-+ |
340 /* ... */ // | |
341 } // free <---+ |
342 /* ... */ // |
343 } // free <------+
344 ~~~~
345
346 # Pointers and Memory
347
348 ## "Owned" Pointers
349
350 ~~~~{.rust}
351 fn f0() -> ~[int] {
352 return ~[1,2,3]; // returning ownership
353 }
354 fn f1() -> ~[int] {
355 let a = ~[1,2,3];
356 let b = a;
357 return a; // error: use of moved value: `a`
358 }
359 fn f2() -> ~[int] {
360 let a = ~[1,2,3];
361 let b = a.clone();
362 return a; // fine now; `a` and `b` both valid
363 }
364 ~~~~
365
366 # Pointers and Memory
367
368 ## "Owned" Pointers
369
370 ~~~~{.rust}
371 #[deriving(Clone)]
372 enum List<T> { Cons(T, ~List<T>), Nil }
373
374 fn f3() -> ~List<int> {
375 let mut a = ~Cons(1, ~Cons(2, ~Nil))
376 /* a is mutable */
377 let b = a;
378 /* can no longer use a, b is immutable */
379 let mut c = b.clone();
380 /* can use both b and c */
381 return b;
382 }
383 ~~~~
384
385 # Pointers and Memory
386
387 ## Dispreferred Style
388
389 ~~~~{.rust}
390 type t8 = (u32,u32,u32,u32,u32,u32,u32,u32);
391
392 fn eight_nums() -> ~t8 {
393 ~(1,2,3,4,5,6,7,8)
394 }
395
396 fn main() {
397 let t: ~t8 = eight_nums();
398 /* ... */
399 }
400 ~~~~
401
402 # Pointers and Memory
403
404 ## Preferred Style
405
406 ~~~~{.rust}
407 type t8 = (u32,u32,u32,u32,u32,u32,u32,u32);
408
409 fn eight_nums() -> t8 {
410 (1,2,3,4,5,6,7,8)
411 }
412
413 fn main() {
414 let t: ~t8 = ~eight_nums();
415 /* ... */
416 }
417 ~~~~
418
419 # Pointers and Memory
420
421 ## References
422
423 ~~~~{.rust}
424 {
425 let p = Point { x: 1.2, y: 3.4 };
426 let q = & p;
427 // both p and q usable
428 }
429 {
430 let q = & Point { x: 1.2, y: 3.4 };
431 }
432 {
433 let p = Point { x: 1.2, y: 3.4 };
434 let r = & p.x;
435 }
436 ~~~~
437
438 # Pointers and Memory
439
440 ## References
441
442 ~~~~{.rust}
443 fn eq(xl: ~List<int>, yl: ~List<int>) -> bool {
444 /* elided */
445 }
446
447 fn main() {
448 let l1 = ~Cons(1, ~Cons (2, ~Nil));
449 let l2 = ~Cons(3, ~Cons (4, ~Nil));
450 println!("{}", eq(l1, l2));
451 println!("{:?}", l1);
452 }
453 ~~~~
454
455 # Pointers and Memory
456
457 ## References
458
459 ~~~~{.rust}
460 fn eq(xl: ~List<int>, yl: ~List<int>) -> bool {
461 /* elided */
462 }
463
464 fn main() {
465 let l1 = ~Cons(1, ~Cons (2, ~Nil));
466 let l2 = ~Cons(3, ~Cons (4, ~Nil));
467 println!("{}", eq(l1, l2)); // ownership of l1 and l2
468 // moves to eq function
469 println!("{:?}", l1); // error: use of moved value!
470 }
471 ~~~~
472
473 # Pointers and Memory
474
475 ## References
476
477 ~~~~{.rust}
478 fn eq(xl: ~List<int>, yl: ~List<int>) -> bool {
479 /* elided */
480 }
481
482 fn main() {
483 let l1 = ~Cons(1, ~Cons (2, ~Nil));
484 let l2 = ~Cons(3, ~Cons (4, ~Nil));
485 println!("{}", eq(l1.clone(), l2.clone()));
486 println!("{:?}", l1);
487 }
488 ~~~~
489
490 # Pointers and Memory
491
492 ## References
493
494 ~~~~{.rust}
495 fn eq(xl: &List<int>, yl: &List<int>) -> bool {
496 /* elided */
497 }
498
499 fn main() {
500 let l1 = ~Cons(1, ~Cons (2, ~Nil));
501 let l2 = ~Cons(3, ~Cons (4, ~Nil));
502 println!("{}", eq(l1, l2));
503 println!("{:?}", l1);
504 }
505 ~~~~
506
507 # Pointers and Memory
508
509 ## References
510
511 ~~~~{.rust}
512 fn eq(xl: &List<int>, yl: &List<int>) -> bool {
513 match (xl, yl) {
514 (&Nil, &Nil) => true,
515 (&Cons(x, ~ref xs), &Cons(y, ~ref ys))
516 if x == y => eq(xs, ys),
517 (_, _) => false
518 }
519 }
520 ~~~~
521
522 # Pointers and Memory
523
524 ## References
525
526 ~~~~{.rust}
527 fn eq<T: Eq>(xl: &List<T>, yl: &List<T>) -> bool {
528 match (xl, yl) {
529 (&Nil, &Nil) => true,
530 (&Cons(x, ~ref xs), &Cons(y, ~ref ys))
531 if x == y => eq(xs, ys),
532 (_, _) => false
533 }
534 }
535 ~~~~
536
537 # Pointers and Memory
538
539 ## References and Lifetimes
540
541 ~~~~{.rust}
542 {
543 let a = ~5;
544 let mut p = &a;
545 {
546 let b = ~8;
547 p = &b;
548 }
549 println!("{}", **p)
550 }
551 ~~~~
552
553
554 # Pointers and Memory
555
556 ## References and Lifetimes
557
558 ~~~~{.rust}
559 {
560 let a = ~5; // malloc |---+
561 let mut p = &a; // |
562 { // |
563 let b = ~8; // malloc |-+ |
564 p = &b; // | |
565 } // free <---+ |
566 println!("{}", **p) // |
567 } // free <-----+
568 ~~~~
569
570
571 # Pointers and Memory
572
573 ## References and Lifetimes
574
575 ~~~~{.rust}
576 {
577 let a = ~5;
578 let mut p = &a;
579 {
580 let b = ~8;
581 p = &b; // error: borrowed value does
582 // not live long enough
583 }
584 println!("{}", **p)
585 }
586 ~~~~
587 # Pointers and Memory
588
589 ## References, Pointers, Mutability
590
591 ~~~~{.rust}
592 {
593 let mut x = ~5;
594 *x = *x + 1;
595 {
596 let y = &x;
597 /* x is not mutable for the rest of this block */
598 }
599 /* x regains mutability */
600 }
601 ~~~~
602
603 # Pointers and Memory
604
605 ## References, Pointers, Mutability
606
607 ~~~~{.rust}
608 enum IntList {
609 Cons { head: int, tail: ~IntList },
610 Nil,
611 }
612 {
613 let mut lst = ~Cons { head: 5, tail: ~Nil };
614 {
615 let y = &(lst.head); // or &((*lst).head)
616 lst = ~Nil;
617 println!("{}", y);
618 }
619 }
620 ~~~~
621
622 # Pointers and Memory
623
624 ## References, Pointers, Mutability
625
626 ~~~~{.rust}
627 enum IntList {
628 Cons { head: int, tail: ~IntList },
629 Nil,
630 }
631 {
632 let mut lst = ~Cons { head: 5, tail: ~Nil };
633 {
634 let y = &(lst.head);
635 lst = ~Nil;
636 println!("{}", y); // BAD
637 }
638 }
639 ~~~~
640
641 # Pointers and Memory
642
643 ## Named Lifetimes
644
645 ~~~~{.rust}
646 fn tail<T>(lst: &List<T>) -> &List<T> {
647 match *lst {
648 Nil => &Nil,
649 Cons(_, ~ref xs) => xs
650 }
651 }
652 ~~~~
653
654 # Pointers and Memory
655
656 ## Named Lifetimes
657
658 ~~~~{.rust}
659 fn tail<'s, T>(lst: &'s List<T>) -> &'s List<T> {
660 match *lst {
661 Nil => &Nil,
662 Cons(_, ~ref xs) => xs
663 }
664 }
665 ~~~~
666
667 # Pointers and Memory
668
669 ## Reference Counting
670
671 ~~~~{.rust}
672 use std::rc::Rc;
673 {
674 let x = Rc::new([1,2,3]);
675 let y = x.clone(); // two references, one vector
676 assert!(x.ptr_eq(y));
677 assert!(*y.borrow() == [1,2,3]);
678 }
679 ~~~~
680
681 ## Garbage Collection
682
683 ~~~~{.rust}
684 use std::gc::Gc;
685 {
686 let x = Gc::new([1,2,3]);
687 // etc.
688 }
689 ~~~~
690
691 # Pointers and Memory
692
693 ## C Pointers
694
695 ~~~~{.rust}
696 use std::ptr::RawPtr;
697
698 #[link(name="foo")]
699 extern {
700 fn unsafe_get() -> *int;
701 }
702
703 fn safe_get() -> Option<int> {
704 unsafe {
705 let i = unsafe_get();
706 i.to_option()
707 }
708 }
709 ~~~~
710
711 # Closures
712
713 # Closures
714
715 > [...] Lambdas are relegated to relative obscurity until Java makes them
716 > popular by not having them.
717 >
718 > —James Iry, "A Brief, Incomplete, and Mostly Wrong History of Programming
719 > Languages"
720
721 # Closures
722
723 ## Functions
724
725 ~~~~{.rust}
726 fn main() {
727 let x = 5;
728 fn inner(y: int) -> int {
729 return x + y;
730 }
731 println!("{}", inner(1));
732 }
733 ~~~~
734
735 # Closures
736
737 ## Functions Do NOT Close Over Env
738
739 ~~~~{.rust}
740 fn main() {
741 let x = 5;
742 fn inner(y: int) -> int {
743 return x + y; // error: can't capture dynamic env
744 }
745 println!("{}", inner(1));
746 }
747 ~~~~
748
749 # Closures
750
751 ## Stack Closure
752
753 ~~~~{.rust}
754 fn main() {
755 let x = 5;
756 let inner = |y| x + y;
757 println!("{}", inner(1));
758 }
759 ~~~~
760
761 ## Stack Closure with Type Annotations
762
763 ~~~~{.rust}
764 fn main() {
765 let x = 5;
766 let inner = |y: int| -> int { x + y };
767 println!("{}", inner(1));
768 }
769 ~~~~
770
771 # Closures
772
773 ## Stack Closures
774
775 ~~~~{.rust}
776 fn my_map<A,B>(f: |&A|->B, l: &List<A>) -> List<B> {
777 match *l {
778 Nil => Nil,
779 Cons(ref x, ~ref xs) =>
780 Cons(f(x)), ~my_map(f, xs))
781 }
782 }
783
784 fn main() {
785 fn incr(x: &int) -> int { x + 1 }
786 let l = ~Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
787 println!("{:?}", my_map(|x| x + 1, l));
788 println!("{:?}", my_map(incr, l));
789 }
790 ~~~~
791
792 # Closures
793
794 ## Owned Closures
795
796 ~~~~{.rust}
797 use std::task::spawn;
798
799 fn main() {
800 let x = ~5;
801 spawn(proc() {
802 println!("{}", x);
803 });
804 // x is now owned by the proc above
805 }
806 ~~~~
807
808 # Methods
809
810 ## Methods on a Struct
811
812 ~~~~{.rust}
813 use std::f64::{sqrt,pow};
814 struct Point { x: f64, y: f64 }
815 impl Point {
816 fn magnitude(&self) -> f64 {
817 sqrt(pow(self.x,2.0)+pow(self.y,2.0))
818 }
819 fn new((my_x, my_y): (f64, f64)) -> Point {
820 Point { x: my_x, y: my_y }
821 }
822 }
823 fn main() {
824 let p = Point::new((2.0,4.0));
825 println!("{}", p.magnitude());
826 }
827 ~~~~
828
829 # Methods
830
831 ## Methods on an Enum
832
833 ~~~~{.rust}
834 impl<T> List<T> {
835 fn is_empty(&self) -> bool {
836 match self {
837 &Nil => true,
838 &Cons(_, _) => false,
839 }
840 }
841 }
842 ~~~~
843
844 # Traits
845
846 ## Head of a List By Reference
847 ~~~~{.rust}
848 fn head<'a, T>(lst: &'a List<T>) -> Option<&'a T> {
849 match lst {
850 &Nil => None,
851 &Cons(ref hd, _) => Some(hd)
852 }
853 }
854 ~~~~
855
856 # Traits
857
858 ## Head of a List By Value
859 ~~~~{.rust}
860 fn head<T>(lst: &List<T>) -> Option<T> {
861 match lst {
862 &Nil => None,
863 &Cons(ref hd, _) => Some(*hd)
864 }
865 }
866 ~~~~
867
868 # Traits
869
870 ## Head of a List By Value
871 ~~~~{.rust}
872 fn head<T>(lst: &List<T>) -> Option<T> {
873 match lst {
874 &Nil => None,
875 &Cons(ref hd, _) => Some(*hd)
876 // cannot move out of dereference of & pointer
877 }
878 }
879 ~~~~
880
881 # Traits
882
883 ## Head of a List By Value
884 ~~~~{.rust}
885 fn head<T: Clone>(lst: &List<T>) -> Option<T> {
886 match lst {
887 &Nil => None,
888 &Cons(ref hd, _) => Some(hd.clone())
889 }
890 }
891 ~~~~
892
893 # Traits
894
895 ## Declaring Traits
896 ~~~~{.rust}
897 trait Printable {
898 fn print(&self);
899 }
900
901 impl Printable for int {
902 fn print(&self) { println!("{}", *self) }
903 }
904
905 impl Printable for bool {
906 fn print(&self) { println!("{}", *self) }
907 }
908
909 fn main() {
910 5.print(); true.print();
911 }
912 ~~~~
913
914 # Traits
915
916 ## Using Multiple Traits
917
918 ~~~~{.rust}
919 fn print_head<T: Clone+Printable>(lst: &List<T>) {
920 match lst {
921 &Nil => { println!("Nothing!") }
922 &Cons(ref hd, _) => { hd.clone().print() }
923 }
924 }
925 ~~~~
926
927 # Traits
928
929 ## Static Dispatch
930
931 ~~~~{.rust}
932 fn printAll<T: Printable>(vec: &[T]) {
933 for p in vec.iter() { p.print() }
934 }
935 fn main() {
936 printAll([1, 2, 3]);
937 }
938 ~~~~
939
940 ## Dynamic Dispatch
941
942 ~~~~{.rust}
943 fn print_all(vec: &[~Printable]) {
944 for p in vec.iter() { p.print() }
945 }
946 fn main() {
947 print_all([~1 as ~Printable, ~true as ~Printable]);
948 }
949 ~~~~
950
951 # Tasks and Communication
952
953 ## Tasks
954
955 ~~~~{.rust}
956 fn main() {
957 spawn(proc() {
958 println!("Hello from another task!");
959 });
960 println!("Hello from the parent task!");
961 }
962 ~~~~
963
964 # Tasks and Communication
965
966 ## Communication
967
968 ~~~~{.rust}
969 fn main() {
970 let (port, chan): (Port<int>, Chan<int>) = Chan::new();
971 spawn(proc() {
972 chan.send(some_computation());
973 });
974 some_other_computation();
975 let result = port.recv();
976 }
977 ~~~~
978
979 # Tasks and Communication
980
981 ## Atomic Reference Counting
982
983 ~~~~{.rust}
984 fn main() {
985 let parent_copy = Arc::new(something_very_large());
986 let (port, chan) = Chan::new();
987 chan.send(parent_copy.clone());
988 spawn(proc() {
989 let task_copy = port.recv();
990 task_copy.get().do_something();
991 });
992 parent_copy.get().do_something_else();
993 }
994 ~~~~
995
996 # Tasks and Communication
997
998 ## Failure
999
1000 ~~~~{.rust}
1001 fn main() {
1002 let r : Result<int, ()> = try(proc() {
1003 if some_operation_succeeds() {
1004 return 5;
1005 } else {
1006 fail!("Hark! An error!");
1007 }
1008 });
1009 match r {
1010 Ok(i) => println!("Got {}", i),
1011 Err(_) => println!("Hark!"),
1012 };
1013 }
1014 ~~~~
1015
1016 # Crates and Modules
1017
1018 - A "crate" is a compilation unit; `rustc` produces a single crate
1019 if it is run (either a library or an executable.)
1020 - A module is a grouping of definitions. Modules can be hierarchical
1021 and can be defined in a single file in `mod { ... }` blocks, or in
1022 separate files.
1023
1024 # Crates and Modules
1025
1026 ## main.rs
1027
1028 ~~~~{.rust}
1029 mod mylist {
1030 pub enum List<T> { Cons(T, ~List<T>), Nil }
1031 pub fn from_vec<T>(mut vec : ~[T]) -> ~List<T> { ... }
1032 impl<T> List<T> {
1033 pub fn length(&self) -> int { ... }
1034 }
1035 }
1036
1037 fn main() {
1038 let v = ~[1,2,3];
1039 let l = ::mylist::from_vec(v);
1040 /* ... */
1041 }
1042 ~~~~
1043
1044 # Crates and Modules
1045
1046 ## mylist.rs or mylist/mod.rs
1047
1048 ~~~~{.rust}
1049 mod mylist {
1050 pub enum List<T> { Cons(T, ~List<T>), Nil }
1051 pub fn from_vec<T>(mut vec : ~[T]) -> ~List<T> { ... }
1052 impl<T> List<T> {
1053 pub fn length(&self) -> int { ... }
1054 }
1055 }
1056 ~~~~
1057
1058 ## main.rs
1059
1060 ~~~~{.rust}
1061 mod mylist;
1062 main() {
1063 let v = ~[1,2,3];
1064 let l = ::mylist::from_vec(v);
1065 /* ... */
1066 }
1067 ~~~~
1068
1069 # Crates and Modules
1070 ## main.rs
1071
1072 ~~~~{.rust}
1073 use mylist::from_vec;
1074 mod mylist;
1075
1076 main() {
1077 let v = ~[1,2,3];
1078 let l = from_vec(v);
1079 /* ... */
1080 }
1081 ~~~~
1082
1083 # Crates and Modules
1084 ## Crate Metadata
1085
1086 ~~~~{.rust}
1087 #[crate_id = "mycrate#1.2"];
1088 #[crate_type = "lib"];
1089 ~~~~
1090
1091 ## Requesting Crate Metadata
1092
1093 ~~~~{.rust}
1094 extern crate mycrate "mycrate#1.2";
1095 extern crate oldmycrate "mycrate#0.6";
1096 ~~~~
1097
1098 # The Future
1099
1100 # The Future
1101
1102 \begin{center}
1103 \includegraphics[width=.9\textwidth]{imgs/flying-machines.jpg}
1104 \end{center}
1105
1106 # The Future
1107
1108 ## Possible Syntax Changes
1109
1110 - `~foo` might become `box foo`
1111 - `~[T]` might become `Vec<T>`
1112 - Operator overloading
1113
1114 ## Possible Language Changes
1115
1116 - Speculations about inheritance, subtyping
1117 - Stronger restrictions on `unsafe` code
1118
1119 ## Standard Library Improvements
1120
1121 ## Package Manager
1 DEPS="rust.tex rust.md"
2 redo-ifchange $DEPS
3 xelatex --output-directory build 1>&2 rust.tex
4 mv build/rust.pdf $3
1 redo-ifchange rust.md
2 pandoc -f markdown -t beamer --standalone --highlight-style haddock \
3 -V theme=Boadilla -V colortheme=beaver --template=my.beamer <rust.md >$3
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct {
5 int x, y;
6 } point;
7
8 point add(point a, point b)
9 {
10 point result = { a.x + b.x, a.y + b.y };
11 return result;
12 }
13
14 int main(int argc, char* argv[])
15 {
16 point a = { 1, 2 };
17 point* b = malloc(sizeof(point));
18 b->x = 4;
19 b->y = 3;
20 point c = add(a, *b);
21 printf("{.x = %d, .y = %d}\n", c.x, c.y);
22 return 0;
23 }
1 #include "stdio.h"
2 #include "stdlib.h"
3 #include <iostream>
4
5 struct point {
6 int x, y;
7 point(int _x, int _y) {
8 x = _x; y = _y;
9 }
10 point add(point other) {
11 return point(x + other.x, y + other.y);
12 }
13 };
14
15 int main(int argc, char* argv[]) {
16 point a(1, 2);
17 point* b = new point(4, 3);
18 point c = a.add(*b);
19 std::cout << "{.x = " << c.x;
20 std::cout << ", .y = " << c.y << "}" << std::endl;
21 delete b;
22 }
1 import core.memory;
2 import std.stdio;
3
4 struct Point {
5 int x, y;
6 Point add(Point other) {
7 return Point(this.x + other.x, this.y + other.y);
8 }
9 }
10
11 void main() {
12 Point a = Point(1, 2);
13 Point* b = cast(Point*)GC.malloc(Point.sizeof);
14 b.x = 4;
15 b.y = 3;
16 writeln(a.add(*b));
17 GC.free(b);
18 }
1 data Point = { x, y : Int }
2
3 addPoint : Point -> Point -> Point
4 addPoint p1 p2 = { x = p1.x + p2.x, y = p1.y + p2.y }
5
6 main : ()
7 main = { let a = { x = 1, y = 2 }
8 ; let b = malloc { x = 4, y = 3}
9 ; print (addPoint a (deref b))
10 ; free(b)
11 }
1 package main
2
3 import "fmt"
4
5 type Point struct { X, Y int }
6
7 func (a Point) add(b Point) Point {
8 return Point{ a.X + b.X, a.Y + b.Y }
9 }
10
11 func main() {
12 a := Point{1, 2}
13 b := new(Point)
14 b.X, b.Y = 4, 3
15 fmt.Println(a.add(*b))
16 }
1 type Point = tuple[x: int, y: int]
2
3 proc add(a: Point, b: Point): Point =
4 (x: a.x + b.x, y: a.y + b.y)
5
6 var a : Point
7 var b : ptr Point
8
9 a = (x: 1, y: 2)
10 b = cast[ptr Point](alloc(sizeof(Point)))
11 b.x = 4
12 b.y = 3
13 echo(add(a, b[]))
14 dealloc(b)
1 struct Point {
2 x: int,
3 y: int
4 }
5
6 impl Point {
7 fn add(self, other: Point) -> Point {
8 Point { x: self.x + other.x,
9 y: self.y + other.y }
10 }
11 }
12
13 fn main() {
14 let a = Point { x: 1, y: 2 };
15 let b = ~Point { x: 4, y: 3 };
16 println!("{:?}", a.add(*b));
17 }
1 if [ -e regexp ]; then rm regexp; fi
1 redo-ifchange regexp
1 use re::instruction::{Instr,IChar,IMatch,IJmp,ISplit};
2 use std::vec::append;
3 mod instruction;
4
5 /* A regular expression parse tree */
6 enum Regexp {
7 RChar(char),
8 RSeq(~Regexp, ~Regexp),
9 RChc(~Regexp, ~Regexp),
10 RRep(~Regexp),
11 }
12
13 /* We're assuming a prefix regexp here. That means that we have
14 * the following operators:
15 * .ab => ab
16 * |ab => a|b
17 * *a => a*
18 * but these nest, so (ab|c)* would become
19 * *|c.ab
20 * This is easier to parse. Deal with it.
21 */
22 fn parse<'a>(s: &'a str) -> (&'a str, Regexp) {
23 match s.char_at(0) {
24 '.' => { let (s1, r1) = parse(s.slice_from(1));
25 let (s2, r2) = parse(s1);
26 (s2, RSeq(~r1, ~r2)) },
27 '|' => { let (s1, r1) = parse(s.slice_from(1));
28 let (s2, r2) = parse(s1);
29 (s2, RChc(~r1, ~r2)) },
30 '*' => { let (s1, r1) = parse(s.slice_from(1));
31 (s1, RRep(~r1)) },
32 c => (s.slice_from(1), RChar(c)),
33 }
34 }
35
36 /* Compiling an AST for regexps to the instructions */
37 fn emit(r: &Regexp, i: uint) -> (uint, ~[Instr]) {
38 match *r {
39 RChar(c) => { (i+1, ~[IChar(c)]) },
40 RSeq(ref a, ref b) =>
41 { let (ai, v1) = emit(*a, i);
42 let (bi, v2) = emit(*b, ai);
43 (bi, append(v1, v2)) },
44 RChc(ref a, ref b) =>
45 { let (ai, v1) = emit(*a, i + 1);
46 let (bi, v2) = emit(*b, ai + 1);
47 let spl = ~[ ISplit(i + 1, ai + 1) ];
48 let jmp = ~[ IJmp(ai) ];
49 (bi, append(spl, append(v1, append(jmp, v2)))) },
50 RRep(ref a) =>
51 { let (ai, v1) = emit(*a, i + 1);
52 let spl = ~[ ISplit(i + 1, ai + 1) ];
53 let jmp = ~[ IJmp(i) ];
54 (ai + 1, append(spl, append(v1, jmp))) },
55 }
56 }
57
58 /* A wrapper over these processes */
59 pub fn compile(s: &str) -> ~[Instr] {
60 let (_, re) = parse(s);
61 println!("{:?}", re);
62 let (_, ins) = emit(&re, 0);
63 println!("{:?}", ins);
64 return append(ins, [IMatch]);
65 }
1 /* A single instruction as used in the VM-based matcher */
2 #[deriving(Clone)]
3 pub enum Instr {
4 IChar(char), /* match a character or fail */
5 IMatch, /* match anything successfully */
6 IJmp(uint) , /* jump to instr i */
7 ISplit(uint, uint), /* try both instrs i and j */
8 }
1 pub use re::compile::compile;
2 pub use re::instruction::{Instr,IChar,IMatch,IJmp,ISplit};
3 pub use re::recursive::eval;
4 pub use re::stack::eval;
5 pub mod compile;
6 pub mod instruction;
7 pub mod recursive;
8 pub mod stack;
1 use re::instruction::{Instr,IChar,IMatch,IJmp,ISplit};
2 mod instruction;
3
4 /* We wrap the real evaluation function, as we're always going to
5 * start executing instruction 0 with no string matched. */
6 pub fn eval(instrs: &[Instr], input: &str) -> bool {
7 eval1(instrs, input, 0, 0)
8 }
9
10 /* We use the Rust stack as our stack in this naive recursive
11 * implementation. */
12 fn eval1(instrs: &[Instr], input: &str, pc: uint, cc: uint) -> bool {
13 match instrs[pc] {
14 IChar(_) if cc >= input.len() => return false,
15 IChar(c) if c == input.char_at(cc) =>
16 eval1(instrs, input, pc + 1, cc + 1),
17 IChar(_) => return false,
18 IMatch => return true,
19 IJmp(i) => eval1(instrs, input, i, cc),
20 ISplit(i, _) if eval1(instrs, input, i, cc) => true,
21 ISplit(_, j) => eval1(instrs, input, j, cc),
22 }
23 }
1 use re::instruction::{Instr,IChar,IMatch,IJmp,ISplit};
2 mod instruction;
3
4 /* The state of a program can be unambiguously specified by
5 * a current instruction and a current position in the string. */
6 struct EvalState { pc: uint, cc: uint }
7
8 /* An evaluator that maintains a manual, mutable stack for doing
9 * regular-expression matching. */
10 pub fn eval(instrs: &[Instr], input: &str) -> bool {
11 let mut stack = ~[ EvalState {pc: 0, cc: 0} ];
12
13 while stack.len() > 0 {
14 let st = stack.pop();
15 match instrs[st.pc] {
16 IChar(_) if st.cc >= input.len() =>
17 continue,
18 IChar(c) if c == input.char_at(st.cc) =>
19 stack.push(EvalState { pc: st.pc + 1, cc: st.cc + 1 }),
20 IChar(_) =>
21 continue,
22 IMatch =>
23 return true,
24 IJmp(i) =>
25 stack.push(EvalState { pc: i, cc: st.cc }),
26 ISplit(i, j) => {
27 stack.push(EvalState { pc: j, cc: st.cc });
28 stack.push(EvalState { pc: i, cc: st.cc });
29 },
30 }
31 }
32 return false;
33 }
1 DEPS="regexp.rs re/compile.rs re/instruction.rs re/mod.rs re/recursive.rs re/stack.rs"
2 redo-ifchange $DEPS
3 rustc regexp.rs -o $3
1 /* This is a basic implementation of a regular expression matcher,
2 * based on Henry Spencer's virtual-machine approach to regular
3 * expression matching outlined by Russ Cox here:
4 * http://swtch.com/~rsc/regexp/regexp2.html
5 *
6 * For ease of parsing, I'm using a highly non-standard Polish
7 * notation for regular expressions, in which . and | are
8 * prefix binary operators for catenation and choice, respectively,
9 * and * is a prefix unary operator for repetition. */
10 use re::compile;
11 mod re;
12
13 fn main() {
14 /* our sample regexp corresponds to /ab*c/ in
15 * the usual notation. */
16 let re = compile("..a*bc");
17 println("Recursive:");
18 println!(" match(re, \"abbbc\")\t== {}",
19 ::re::recursive::eval(re, "abbbc"));
20 println!(" match(re, \"ac\")\t== {}",
21 ::re::recursive::eval(re, "ac"));
22 println!(" match(re, \"abd\")\t== {}",
23 ::re::recursive::eval(re, "abd"));
24 println("Manual Stack:");
25 println!(" match(re, \"abbbc\")\t== {}",
26 ::re::stack::eval(re, "abbbc"));
27 println!(" match(re, \"ac\")\t== {}",
28 ::re::stack::eval(re, "ac"));
29 println!(" match(re, \"abd\")\t== {}",
30 ::re::stack::eval(re, "abd"));
31 }