1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 001help.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v1">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #d0d0d0; background-color: #080808; }
body { font-family: monospace; color: #d0d0d0; background-color: #080808; }
* { font-size: 1em; }
.cSpecial { color: #008000; }
.Constant { color: #008080; }
.Comment { color: #8080ff; }
.Delimiter { color: #c000c0; }
.SalientComment { color: #00ffff; }
.Identifier { color: #008080; }
.PreProc { color: #c000c0; }
-->
</style>
<script type='text/javascript'>
<!--
-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Everything this project/binary supports.</span>
<span class="Comment">//: This should give you a sense for what to look forward to in later layers.</span>
<span class="Delimiter">:(before "End Commandline Parsing")</span>
if <span class="Delimiter">(</span>argc <= <span class="Constant">1</span> || is_equal<span class="Delimiter">(</span>argv[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"--help"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span>
<span class="Comment">// this is the functionality later layers will provide</span>
<span class="Comment">// currently no automated tests for commandline arg parsing</span>
cerr << <span class="Constant">"To load files and run 'main':</span><span class="cSpecial">\n</span><span class="Constant">"</span>
<< <span class="Constant">" mu file1.mu file2.mu ...</span><span class="cSpecial">\n</span><span class="Constant">"</span>
<< <span class="Constant">"To run all tests:</span><span class="cSpecial">\n</span><span class="Constant">"</span>
<< <span class="Constant">" mu test</span><span class="cSpecial">\n</span><span class="Constant">"</span>
<< <span class="Constant">"To load files and then run all tests:</span><span class="cSpecial">\n</span><span class="Constant">"</span>
<< <span class="Constant">" mu test file1.mu file2.mu ...</span><span class="cSpecial">\n</span><span class="Constant">"</span>
<span class="Delimiter">;</span>
<span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="SalientComment">//:: Helper function used by the above fragment of code (and later layers too,</span>
<span class="SalientComment">//:: who knows?).</span>
<span class="Comment">//: The :(code) directive appends function definitions to the end of the</span>
<span class="Comment">//: project. Regardless of where functions are defined, we can call them</span>
<span class="Comment">//: anywhere we like as long as we format the function header in a specific</span>
<span class="Comment">//: way: put it all on a single line without indent, end the line with ') {'</span>
<span class="Comment">//: and no trailing whitespace. As long as functions uniformly start this</span>
<span class="Comment">//: way, our makefile contains a little command to automatically generate</span>
<span class="Comment">//: declarations for them.</span>
<span class="Delimiter">:(code)</span>
bool is_equal<span class="Delimiter">(</span>char* s<span class="Delimiter">,</span> const char* lit<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Identifier">return</span> strncmp<span class="Delimiter">(</span>s<span class="Delimiter">,</span> lit<span class="Delimiter">,</span> strlen<span class="Delimiter">(</span>lit<span class="Delimiter">))</span> == <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Comment">// I'll throw some style conventions here for want of a better place for them.</span>
<span class="Comment">// As a rule I hate style guides. Do what you want, that's my motto. But since</span>
<span class="Comment">// we're dealing with C/C++, the one big thing we want to avoid is undefined</span>
<span class="Comment">// behavior. If a compiler ever encounters undefined behavior it can make</span>
<span class="Comment">// your program do anything it wants.</span>
<span class="Comment">//</span>
<span class="Comment">// For reference, my checklist of undefined behaviors to watch out for:</span>
<span class="Comment">// out-of-bounds access</span>
<span class="Comment">// uninitialized variables</span>
<span class="Comment">// use after free</span>
<span class="Comment">// dereferencing invalid pointers: null, a new of size 0, others</span>
<span class="Comment">//</span>
<span class="Comment">// casting a large number to a type too small to hold it</span>
<span class="Comment">//</span>
<span class="Comment">// integer overflow</span>
<span class="Comment">// division by zero and other undefined expressions</span>
<span class="Comment">// left-shift by negative count</span>
<span class="Comment">// shifting values by more than or equal to the number of bits they contain</span>
<span class="Comment">// bitwise operations on signed numbers</span>
<span class="Comment">//</span>
<span class="Comment">// Converting pointers to types of different alignment requirements</span>
<span class="Comment">// T* -> void* -> T*: defined</span>
<span class="Comment">// T* -> U* -> T*: defined if non-function pointers and alignment requirements are same</span>
<span class="Comment">// function pointers may be cast to other function pointers</span>
<span class="Comment">//</span>
<span class="Comment">// Casting a numeric value into a value that can't be represented by the target type (either directly or via static_cast)</span>
<span class="Comment">//</span>
<span class="Comment">// To guard against these, some conventions:</span>
<span class="Comment">//</span>
<span class="Comment">// 0. Initialize all primitive variables in functions and constructors.</span>
<span class="Comment">//</span>
<span class="Comment">// 1. Minimize use of pointers and pointer arithmetic. Avoid 'new' and</span>
<span class="Comment">// 'delete' as far as possible. Rely on STL to perform memory management to</span>
<span class="Comment">// avoid use-after-free issues (and memory leaks).</span>
<span class="Comment">//</span>
<span class="Comment">// 2. Avoid naked arrays to avoid out-of-bounds access. Never use operator[]</span>
<span class="Comment">// except with map. Use at() with STL vectors and so on.</span>
<span class="Comment">//</span>
<span class="Comment">// 3. Valgrind all the things.</span>
<span class="Comment">//</span>
<span class="Comment">// 4. Avoid unsigned numbers. Not strictly an undefined-behavior issue, but</span>
<span class="Comment">// the extra range doesn't matter, and it's one less confusing category of</span>
<span class="Comment">// interaction gotchas to worry about.</span>
<span class="Comment">//</span>
<span class="Comment">// Corollary: don't use the size() method on containers, since it returns an</span>
<span class="Comment">// unsigned and that'll cause warnings about mixing signed and unsigned,</span>
<span class="Comment">// yadda-yadda. Instead use this macro below to perform an unsafe cast to</span>
<span class="Comment">// signed. We'll just give up immediately if a container's every too large.</span>
<span class="Delimiter">:(before "End Includes")</span>
<span class="PreProc">#define SIZE(X) (assert(X</span><span class="Delimiter">.</span><span class="PreProc">size() < (</span><span class="Constant">1LL</span><span class="PreProc"><<</span><span class="Constant">62</span><span class="PreProc">))</span><span class="Delimiter">,</span><span class="PreProc"> </span>static_cast<span class="PreProc"><</span>long<span class="PreProc"> </span>long<span class="PreProc"> </span>int<span class="PreProc">>(X</span><span class="Delimiter">.</span><span class="PreProc">size()))</span>
<span class="Comment">//</span>
<span class="Comment">// 5. Integer overflow is still impossible to guard against. Maybe after</span>
<span class="Comment">// reading <a href="http://www.cs.utah.edu/~regehr/papers/overflow12.pdf">http://www.cs.utah.edu/~regehr/papers/overflow12.pdf</a></span>
<span class="Delimiter">:(before "End Includes")</span>
<span class="PreProc">#include</span><span class="Constant"><assert.h></span>
<span class="PreProc">#include</span><span class="Constant"><iostream></span>
using std::istream<span class="Delimiter">;</span>
using std::ostream<span class="Delimiter">;</span>
using std::iostream<span class="Delimiter">;</span>
using std::cin<span class="Delimiter">;</span>
using std::cout<span class="Delimiter">;</span>
using std::cerr<span class="Delimiter">;</span>
<span class="PreProc">#include</span><span class="Constant"><cstring></span>
<span class="PreProc">#include</span><span class="Constant"><string></span>
using std::string<span class="Delimiter">;</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|