2015-04-24 03:35:31 +00:00
|
|
|
//: Everything this project/binary supports.
|
|
|
|
//: This should give you a sense for what to look forward to in later layers.
|
|
|
|
|
2015-04-22 20:29:02 +00:00
|
|
|
:(before "End Commandline Parsing")
|
|
|
|
if (argc <= 1 || is_equal(argv[1], "--help")) {
|
|
|
|
// this is the functionality later layers will provide
|
|
|
|
// currently no automated tests for commandline arg parsing
|
|
|
|
cerr << "To load files and run 'main':\n"
|
|
|
|
<< " mu file1.mu file2.mu ...\n"
|
|
|
|
<< "To run all tests:\n"
|
|
|
|
<< " mu test\n"
|
|
|
|
<< "To load files and then run all tests:\n"
|
|
|
|
<< " mu test file1.mu file2.mu ...\n"
|
2015-09-26 18:07:50 +00:00
|
|
|
<< "To load all files with a numeric prefix in a directory:\n"
|
|
|
|
<< " mu directory1\n"
|
|
|
|
<< "You can test directories just like files.\n"
|
|
|
|
<< "To pass ingredients to a mu program, provide them after '--':\n"
|
|
|
|
<< " mu file_or_dir1 file_or_dir2 ... -- ingredient1 ingredient2 ...\n"
|
2015-04-22 20:29:02 +00:00
|
|
|
;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-24 03:35:31 +00:00
|
|
|
//:: Helper function used by the above fragment of code (and later layers too,
|
|
|
|
//:: who knows?).
|
|
|
|
//: The :(code) directive appends function definitions to the end of the
|
|
|
|
//: project. Regardless of where functions are defined, we can call them
|
|
|
|
//: anywhere we like as long as we format the function header in a specific
|
|
|
|
//: way: put it all on a single line without indent, end the line with ') {'
|
|
|
|
//: and no trailing whitespace. As long as functions uniformly start this
|
|
|
|
//: way, our makefile contains a little command to automatically generate
|
|
|
|
//: declarations for them.
|
2015-04-22 20:29:02 +00:00
|
|
|
:(code)
|
|
|
|
bool is_equal(char* s, const char* lit) {
|
|
|
|
return strncmp(s, lit, strlen(lit)) == 0;
|
|
|
|
}
|
|
|
|
|
2015-05-17 09:22:41 +00:00
|
|
|
// I'll throw some style conventions here for want of a better place for them.
|
|
|
|
// As a rule I hate style guides. Do what you want, that's my motto. But since
|
|
|
|
// we're dealing with C/C++, the one big thing we want to avoid is undefined
|
2015-05-18 01:41:10 +00:00
|
|
|
// behavior. If a compiler ever encounters undefined behavior it can make
|
|
|
|
// your program do anything it wants.
|
|
|
|
//
|
|
|
|
// For reference, my checklist of undefined behaviors to watch out for:
|
|
|
|
// out-of-bounds access
|
|
|
|
// uninitialized variables
|
|
|
|
// use after free
|
|
|
|
// dereferencing invalid pointers: null, a new of size 0, others
|
|
|
|
//
|
|
|
|
// casting a large number to a type too small to hold it
|
|
|
|
//
|
|
|
|
// integer overflow
|
|
|
|
// division by zero and other undefined expressions
|
|
|
|
// left-shift by negative count
|
|
|
|
// shifting values by more than or equal to the number of bits they contain
|
|
|
|
// bitwise operations on signed numbers
|
|
|
|
//
|
|
|
|
// Converting pointers to types of different alignment requirements
|
|
|
|
// T* -> void* -> T*: defined
|
|
|
|
// T* -> U* -> T*: defined if non-function pointers and alignment requirements are same
|
|
|
|
// function pointers may be cast to other function pointers
|
|
|
|
//
|
|
|
|
// Casting a numeric value into a value that can't be represented by the target type (either directly or via static_cast)
|
|
|
|
//
|
|
|
|
// To guard against these, some conventions:
|
|
|
|
//
|
|
|
|
// 0. Initialize all primitive variables in functions and constructors.
|
|
|
|
//
|
|
|
|
// 1. Minimize use of pointers and pointer arithmetic. Avoid 'new' and
|
|
|
|
// 'delete' as far as possible. Rely on STL to perform memory management to
|
|
|
|
// avoid use-after-free issues (and memory leaks).
|
|
|
|
//
|
|
|
|
// 2. Avoid naked arrays to avoid out-of-bounds access. Never use operator[]
|
|
|
|
// except with map. Use at() with STL vectors and so on.
|
|
|
|
//
|
2015-05-17 09:22:41 +00:00
|
|
|
// 3. Valgrind all the things.
|
2015-05-18 01:41:10 +00:00
|
|
|
//
|
2015-05-17 09:22:41 +00:00
|
|
|
// 4. Avoid unsigned numbers. Not strictly an undefined-behavior issue, but
|
|
|
|
// the extra range doesn't matter, and it's one less confusing category of
|
|
|
|
// interaction gotchas to worry about.
|
|
|
|
//
|
|
|
|
// Corollary: don't use the size() method on containers, since it returns an
|
|
|
|
// unsigned and that'll cause warnings about mixing signed and unsigned,
|
|
|
|
// yadda-yadda. Instead use this macro below to perform an unsafe cast to
|
2015-09-26 18:01:41 +00:00
|
|
|
// signed. We'll just give up immediately if a container's ever too large.
|
2015-05-17 09:22:41 +00:00
|
|
|
:(before "End Includes")
|
2015-09-12 21:39:20 +00:00
|
|
|
#define SIZE(X) (assert((X).size() < (1LL<<(sizeof(long long int)*8-2))), static_cast<long long int>((X).size()))
|
2015-05-18 01:41:10 +00:00
|
|
|
//
|
|
|
|
// 5. Integer overflow is still impossible to guard against. Maybe after
|
|
|
|
// reading http://www.cs.utah.edu/~regehr/papers/overflow12.pdf
|
2015-05-17 09:22:41 +00:00
|
|
|
|
2015-04-22 20:29:02 +00:00
|
|
|
:(before "End Includes")
|
2015-05-06 01:15:09 +00:00
|
|
|
#include<assert.h>
|
|
|
|
|
2015-04-22 20:29:02 +00:00
|
|
|
#include<iostream>
|
|
|
|
using std::istream;
|
|
|
|
using std::ostream;
|
|
|
|
using std::iostream;
|
|
|
|
using std::cin;
|
|
|
|
using std::cout;
|
|
|
|
using std::cerr;
|
|
|
|
|
|
|
|
#include<cstring>
|
|
|
|
#include<string>
|
|
|
|
using std::string;
|