use find not echo; this also brings fuzzer under the iron fist of tidy.py!
This commit is contained in:
parent
27f1c2b742
commit
d2482fd763
7 changed files with 94 additions and 76 deletions
34
mk/tests.mk
34
mk/tests.mk
|
@ -2,11 +2,6 @@
|
||||||
# Testing variables
|
# Testing variables
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
SOME_TEST_INPUTS = $(wildcard $(S)src/test/*/*.rs)
|
|
||||||
|
|
||||||
SOME_MOAR_TEST_INPUTS = $(wildcard $(S)src/test/*/*/*.rs \
|
|
||||||
$(S)src/test/*/*.rc)
|
|
||||||
|
|
||||||
RPASS_RC := $(wildcard $(S)src/test/run-pass/*.rc)
|
RPASS_RC := $(wildcard $(S)src/test/run-pass/*.rc)
|
||||||
RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs)
|
RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs)
|
||||||
RFAIL_RC := $(wildcard $(S)src/test/run-fail/*.rc)
|
RFAIL_RC := $(wildcard $(S)src/test/run-fail/*.rc)
|
||||||
|
@ -124,34 +119,13 @@ ALL_HS := $(filter-out $(S)src/rt/vg/valgrind.h \
|
||||||
|
|
||||||
tidy:
|
tidy:
|
||||||
@$(call E, check: formatting)
|
@$(call E, check: formatting)
|
||||||
$(Q)echo \
|
$(Q)find $(S)src -name '*.r[sc]' \
|
||||||
$(wildcard $(S)src/etc/*.py) \
|
|
||||||
$(COMPILER_CRATE) \
|
|
||||||
$(COMPILER_INPUTS) \
|
|
||||||
$(LIBRUSTSYNTAX_CRATE) \
|
|
||||||
$(LIBRUSTSYNTAX_INPUTS) \
|
|
||||||
$(CORELIB_CRATE) \
|
|
||||||
$(CORELIB_INPUTS) \
|
|
||||||
| xargs -n 10 python $(S)src/etc/tidy.py
|
| xargs -n 10 python $(S)src/etc/tidy.py
|
||||||
$(Q)echo \
|
$(Q)find $(S)src/etc -name '*.py' \
|
||||||
$(STDLIB_CRATE) \
|
|
||||||
$(STDLIB_INPUTS) \
|
|
||||||
$(COMPILETEST_CRATE) \
|
|
||||||
$(COMPILETEST_INPUTS) \
|
|
||||||
$(CARGO_CRATE) \
|
|
||||||
$(CARGO_INPUTS) \
|
|
||||||
$(RUSTDOC_CRATE) \
|
|
||||||
$(RUSTDOC_INPUTS) \
|
|
||||||
| xargs -n 10 python $(S)src/etc/tidy.py
|
| xargs -n 10 python $(S)src/etc/tidy.py
|
||||||
$(Q)echo \
|
$(Q)echo $(ALL_CS) \
|
||||||
$(SOME_TEST_INPUTS) \
|
|
||||||
| xargs -n 10 python $(S)src/etc/tidy.py
|
| xargs -n 10 python $(S)src/etc/tidy.py
|
||||||
$(Q)echo \
|
$(Q)echo $(ALL_HS) \
|
||||||
$(SOME_MOAR_TEST_INPUTS) \
|
|
||||||
| xargs -n 10 python $(S)src/etc/tidy.py
|
|
||||||
$(Q)echo \
|
|
||||||
$(ALL_CS) \
|
|
||||||
$(ALL_HS) \
|
|
||||||
| xargs -n 10 python $(S)src/etc/tidy.py
|
| xargs -n 10 python $(S)src/etc/tidy.py
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std;
|
use std;
|
||||||
import vec;
|
import vec;
|
||||||
|
|
||||||
fn vec_equal<T>(v: [T], u: [T], element_equality_test: fn@(&&T, &&T) -> bool) ->
|
fn vec_equal<T>(v: [T], u: [T],
|
||||||
|
element_equality_test: fn@(&&T, &&T) -> bool) ->
|
||||||
bool {
|
bool {
|
||||||
let Lv = vec::len(v);
|
let Lv = vec::len(v);
|
||||||
if Lv != vec::len(u) { ret false; }
|
if Lv != vec::len(u) { ret false; }
|
||||||
|
|
|
@ -3,10 +3,14 @@ import std::rand;
|
||||||
import uint::range;
|
import uint::range;
|
||||||
|
|
||||||
// random uint less than n
|
// random uint less than n
|
||||||
fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n }
|
fn under(r : rand::rng, n : uint) -> uint {
|
||||||
|
assert n != 0u; r.next() as uint % n
|
||||||
|
}
|
||||||
|
|
||||||
// random choice from a vec
|
// random choice from a vec
|
||||||
fn choice<T: copy>(r : rand::rng, v : [const T]) -> T { assert vec::len(v) != 0u; v[under(r, vec::len(v))] }
|
fn choice<T: copy>(r : rand::rng, v : [const T]) -> T {
|
||||||
|
assert vec::len(v) != 0u; v[under(r, vec::len(v))]
|
||||||
|
}
|
||||||
|
|
||||||
// k in n chance of being true
|
// k in n chance of being true
|
||||||
fn likelihood(r : rand::rng, k : uint, n : uint) -> bool { under(r, n) < k }
|
fn likelihood(r : rand::rng, k : uint, n : uint) -> bool { under(r, n) < k }
|
||||||
|
@ -68,7 +72,8 @@ fn test_cycles(r : rand::rng, k: uint, n: uint)
|
||||||
if (likelihood(r, k, n)) { v[i].c = @p(choice(r, v)); }
|
if (likelihood(r, k, n)) { v[i].c = @p(choice(r, v)); }
|
||||||
|
|
||||||
if (likelihood(r, k, n)) { v[i].f = bind nopP(choice(r, v)); }
|
if (likelihood(r, k, n)) { v[i].f = bind nopP(choice(r, v)); }
|
||||||
//if (false) { v[i].g = bind (fn~(_x: @pointy) { })(choice(r, v)); }
|
//if (false) { v[i].g = bind (fn~(_x: @pointy) { })(
|
||||||
|
// choice(r, v)); }
|
||||||
// https://github.com/mozilla/rust/issues/1899
|
// https://github.com/mozilla/rust/issues/1899
|
||||||
|
|
||||||
if (likelihood(r, k, n)) { v[i].m = [p(choice(r, v))]; }
|
if (likelihood(r, k, n)) { v[i].m = [p(choice(r, v))]; }
|
||||||
|
|
|
@ -44,7 +44,8 @@ fn common_exprs() -> [ast::expr] {
|
||||||
[dse(ast::expr_break),
|
[dse(ast::expr_break),
|
||||||
dse(ast::expr_cont),
|
dse(ast::expr_cont),
|
||||||
dse(ast::expr_fail(option::none)),
|
dse(ast::expr_fail(option::none)),
|
||||||
dse(ast::expr_fail(option::some(@dse(ast::expr_lit(@dsl(ast::lit_str("boo"))))))),
|
dse(ast::expr_fail(option::some(
|
||||||
|
@dse(ast::expr_lit(@dsl(ast::lit_str("boo"))))))),
|
||||||
dse(ast::expr_ret(option::none)),
|
dse(ast::expr_ret(option::none)),
|
||||||
dse(ast::expr_lit(@dsl(ast::lit_nil))),
|
dse(ast::expr_lit(@dsl(ast::lit_nil))),
|
||||||
dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
|
dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
|
||||||
|
@ -64,9 +65,9 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
|
||||||
alt tm {
|
alt tm {
|
||||||
tm_converge {
|
tm_converge {
|
||||||
alt e.node {
|
alt e.node {
|
||||||
// If the fuzzer moves a block-ending-in-semicolon into callee position,
|
// If the fuzzer moves a block-ending-in-semicolon into callee
|
||||||
// the pretty-printer can't preserve this even by parenthesizing!!
|
// position, the pretty-printer can't preserve this even by
|
||||||
// See email to marijn.
|
// parenthesizing!! See email to marijn.
|
||||||
ast::expr_if(_, _, _) { false }
|
ast::expr_if(_, _, _) { false }
|
||||||
ast::expr_if_check(_, _, _) { false }
|
ast::expr_if_check(_, _, _) { false }
|
||||||
ast::expr_block(_) { false }
|
ast::expr_block(_) { false }
|
||||||
|
@ -166,18 +167,21 @@ fn safe_to_replace_expr(e: ast::expr_, _tm: test_mode) -> bool {
|
||||||
fn safe_to_replace_ty(t: ast::ty_, _tm: test_mode) -> bool {
|
fn safe_to_replace_ty(t: ast::ty_, _tm: test_mode) -> bool {
|
||||||
alt t {
|
alt t {
|
||||||
ast::ty_infer { false } // always implicit, always top level
|
ast::ty_infer { false } // always implicit, always top level
|
||||||
ast::ty_bot { false } // in source, can only appear as the out type of a function
|
ast::ty_bot { false } // in source, can only appear
|
||||||
|
// as the out type of a function
|
||||||
ast::ty_mac(_) { false }
|
ast::ty_mac(_) { false }
|
||||||
_ { true }
|
_ { true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
|
// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
|
||||||
fn replace_expr_in_crate(crate: ast::crate, i: uint, newexpr: ast::expr, tm: test_mode) ->
|
fn replace_expr_in_crate(crate: ast::crate, i: uint,
|
||||||
|
newexpr: ast::expr, tm: test_mode) ->
|
||||||
ast::crate {
|
ast::crate {
|
||||||
let j: @mut uint = @mut 0u;
|
let j: @mut uint = @mut 0u;
|
||||||
fn fold_expr_rep(j_: @mut uint, i_: uint, newexpr_: ast::expr_,
|
fn fold_expr_rep(j_: @mut uint, i_: uint, newexpr_: ast::expr_,
|
||||||
original: ast::expr_, fld: fold::ast_fold, tm_: test_mode) ->
|
original: ast::expr_, fld: fold::ast_fold,
|
||||||
|
tm_: test_mode) ->
|
||||||
ast::expr_ {
|
ast::expr_ {
|
||||||
*j_ += 1u;
|
*j_ += 1u;
|
||||||
if i_ + 1u == *j_ && safe_to_replace_expr(original, tm_) {
|
if i_ + 1u == *j_ && safe_to_replace_expr(original, tm_) {
|
||||||
|
@ -187,8 +191,9 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, newexpr: ast::expr, tm: tes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let afp =
|
let afp =
|
||||||
{fold_expr: fold::wrap(bind fold_expr_rep(j, i, newexpr.node, _, _, tm))
|
{fold_expr: fold::wrap(bind fold_expr_rep(j, i,
|
||||||
with *fold::default_ast_fold()};
|
newexpr.node, _, _, tm))
|
||||||
|
with *fold::default_ast_fold()};
|
||||||
let af = fold::make_fold(afp);
|
let af = fold::make_fold(afp);
|
||||||
let crate2: @ast::crate = @af.fold_crate(crate);
|
let crate2: @ast::crate = @af.fold_crate(crate);
|
||||||
*crate2
|
*crate2
|
||||||
|
@ -196,11 +201,12 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, newexpr: ast::expr, tm: tes
|
||||||
|
|
||||||
|
|
||||||
// Replace the |i|th ty (in fold order) of |crate| with |newty|.
|
// Replace the |i|th ty (in fold order) of |crate| with |newty|.
|
||||||
fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty, tm: test_mode) ->
|
fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty,
|
||||||
ast::crate {
|
tm: test_mode) -> ast::crate {
|
||||||
let j: @mut uint = @mut 0u;
|
let j: @mut uint = @mut 0u;
|
||||||
fn fold_ty_rep(j_: @mut uint, i_: uint, newty_: ast::ty_,
|
fn fold_ty_rep(j_: @mut uint, i_: uint, newty_: ast::ty_,
|
||||||
original: ast::ty_, fld: fold::ast_fold, tm_: test_mode) ->
|
original: ast::ty_, fld: fold::ast_fold,
|
||||||
|
tm_: test_mode) ->
|
||||||
ast::ty_ {
|
ast::ty_ {
|
||||||
*j_ += 1u;
|
*j_ += 1u;
|
||||||
if i_ + 1u == *j_ && safe_to_replace_ty(original, tm_) {
|
if i_ + 1u == *j_ && safe_to_replace_ty(original, tm_) {
|
||||||
|
@ -233,8 +239,11 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
|
||||||
let stolen = steal(crate, cx.mode);
|
let stolen = steal(crate, cx.mode);
|
||||||
let extra_exprs = vec::filter(common_exprs(),
|
let extra_exprs = vec::filter(common_exprs(),
|
||||||
bind safe_to_use_expr(_, cx.mode));
|
bind safe_to_use_expr(_, cx.mode));
|
||||||
check_variants_T(crate, codemap, filename, "expr", extra_exprs + stolen.exprs, pprust::expr_to_str, replace_expr_in_crate, cx);
|
check_variants_T(crate, codemap, filename, "expr",
|
||||||
check_variants_T(crate, codemap, filename, "ty", stolen.tys, pprust::ty_to_str, replace_ty_in_crate, cx);
|
extra_exprs + stolen.exprs, pprust::expr_to_str,
|
||||||
|
replace_expr_in_crate, cx);
|
||||||
|
check_variants_T(crate, codemap, filename, "ty", stolen.tys,
|
||||||
|
pprust::ty_to_str, replace_ty_in_crate, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_variants_T<T: copy>(
|
fn check_variants_T<T: copy>(
|
||||||
|
@ -247,7 +256,8 @@ fn check_variants_T<T: copy>(
|
||||||
replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate,
|
replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate,
|
||||||
cx: context
|
cx: context
|
||||||
) {
|
) {
|
||||||
#error("%s contains %u %s objects", filename, vec::len(things), thing_label);
|
#error("%s contains %u %s objects", filename,
|
||||||
|
vec::len(things), thing_label);
|
||||||
|
|
||||||
let L = vec::len(things);
|
let L = vec::len(things);
|
||||||
|
|
||||||
|
@ -257,8 +267,8 @@ fn check_variants_T<T: copy>(
|
||||||
under(uint::min(L, 30u)) {|j|
|
under(uint::min(L, 30u)) {|j|
|
||||||
log(error, "With... " + stringifier(@things[j]));
|
log(error, "With... " + stringifier(@things[j]));
|
||||||
let crate2 = @replacer(crate, i, things[j], cx.mode);
|
let crate2 = @replacer(crate, i, things[j], cx.mode);
|
||||||
// It would be best to test the *crate* for stability, but testing the
|
// It would be best to test the *crate* for stability, but
|
||||||
// string for stability is easier and ok for now.
|
// testing the string for stability is easier and ok for now.
|
||||||
let handler = diagnostic::mk_handler(none);
|
let handler = diagnostic::mk_handler(none);
|
||||||
let str3 =
|
let str3 =
|
||||||
@as_str(bind pprust::print_crate(
|
@as_str(bind pprust::print_crate(
|
||||||
|
@ -273,8 +283,11 @@ fn check_variants_T<T: copy>(
|
||||||
check_roundtrip_convergence(str3, 1u);
|
check_roundtrip_convergence(str3, 1u);
|
||||||
}
|
}
|
||||||
tm_run {
|
tm_run {
|
||||||
let file_label = #fmt("rusttmp/%s_%s_%u_%u", last_part(filename), thing_label, i, j);
|
let file_label = #fmt("rusttmp/%s_%s_%u_%u",
|
||||||
let safe_to_run = !(content_is_dangerous_to_run(*str3) || has_raw_pointers(*crate2));
|
last_part(filename),
|
||||||
|
thing_label, i, j);
|
||||||
|
let safe_to_run = !(content_is_dangerous_to_run(*str3)
|
||||||
|
|| has_raw_pointers(*crate2));
|
||||||
check_whole_compiler(*str3, file_label, safe_to_run);
|
check_whole_compiler(*str3, file_label, safe_to_run);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,9 +305,11 @@ enum happiness { passed, cleanly_rejected(str), known_bug(str), failed(str), }
|
||||||
|
|
||||||
// We'd find more bugs if we could take an AST here, but
|
// We'd find more bugs if we could take an AST here, but
|
||||||
// - that would find many "false positives" or unimportant bugs
|
// - that would find many "false positives" or unimportant bugs
|
||||||
// - that would be tricky, requiring use of tasks or serialization or randomness.
|
// - that would be tricky, requiring use of tasks or serialization
|
||||||
|
// or randomness.
|
||||||
// This seems to find plenty of bugs as it is :)
|
// This seems to find plenty of bugs as it is :)
|
||||||
fn check_whole_compiler(code: str, suggested_filename_prefix: str, allow_running: bool) {
|
fn check_whole_compiler(code: str, suggested_filename_prefix: str,
|
||||||
|
allow_running: bool) {
|
||||||
let filename = suggested_filename_prefix + ".rs";
|
let filename = suggested_filename_prefix + ".rs";
|
||||||
write_file(filename, code);
|
write_file(filename, code);
|
||||||
|
|
||||||
|
@ -331,7 +346,9 @@ fn removeDirIfExists(filename: str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_running(exe_filename: str) -> happiness {
|
fn check_running(exe_filename: str) -> happiness {
|
||||||
let p = run::program_output("/Users/jruderman/scripts/timed_run_rust_program.py", [exe_filename]);
|
let p = run::program_output(
|
||||||
|
"/Users/jruderman/scripts/timed_run_rust_program.py",
|
||||||
|
[exe_filename]);
|
||||||
let comb = p.out + "\n" + p.err;
|
let comb = p.out + "\n" + p.err;
|
||||||
if str::len(comb) > 1u {
|
if str::len(comb) > 1u {
|
||||||
log(error, "comb comb comb: " + comb);
|
log(error, "comb comb comb: " + comb);
|
||||||
|
@ -352,17 +369,26 @@ fn check_running(exe_filename: str) -> happiness {
|
||||||
0 { passed }
|
0 { passed }
|
||||||
100 { cleanly_rejected("running: explicit fail") }
|
100 { cleanly_rejected("running: explicit fail") }
|
||||||
101 | 247 { cleanly_rejected("running: timed out") }
|
101 | 247 { cleanly_rejected("running: timed out") }
|
||||||
245 | 246 | 138 | 252 { known_bug("https://github.com/mozilla/rust/issues/1466") }
|
245 | 246 | 138 | 252 {
|
||||||
136 | 248 { known_bug("SIGFPE - https://github.com/mozilla/rust/issues/944") }
|
known_bug("https://github.com/mozilla/rust/issues/1466")
|
||||||
rc { failed("Rust program ran but exited with status " + int::str(rc)) }
|
}
|
||||||
|
136 | 248 {
|
||||||
|
known_bug(
|
||||||
|
"SIGFPE - https://github.com/mozilla/rust/issues/944")
|
||||||
|
}
|
||||||
|
rc {
|
||||||
|
failed("Rust program ran but exited with status " +
|
||||||
|
int::str(rc))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_compiling(filename: str) -> happiness {
|
fn check_compiling(filename: str) -> happiness {
|
||||||
let p = run::program_output(
|
let p = run::program_output(
|
||||||
"/Users/jruderman/code/rust/build/x86_64-apple-darwin/stage1/bin/rustc",
|
"/Users/jruderman/code/rust/build/x86_64-apple-darwin/\
|
||||||
[filename]);
|
stage1/bin/rustc",
|
||||||
|
[filename]);
|
||||||
|
|
||||||
//#error("Status: %d", p.status);
|
//#error("Status: %d", p.status);
|
||||||
if p.status == 0 {
|
if p.status == 0 {
|
||||||
|
@ -454,10 +480,11 @@ fn content_might_not_converge(code: str) -> bool {
|
||||||
let confusing_patterns =
|
let confusing_patterns =
|
||||||
["xfail-test",
|
["xfail-test",
|
||||||
"xfail-pretty",
|
"xfail-pretty",
|
||||||
"self", // crazy rules enforced by parser rather than typechecker?
|
"self", // crazy rules enforced by parser not typechecker?
|
||||||
"spawn", // precedence issues?
|
"spawn", // precedence issues?
|
||||||
"bind", // precedence issues?
|
"bind", // precedence issues?
|
||||||
" be ", // don't want to replace its child with a non-call: "Non-call expression in tail call"
|
" be ", // don't want to replace its child with a non-call:
|
||||||
|
// "Non-call expression in tail call"
|
||||||
"\n\n\n\n\n" // https://github.com/mozilla/rust/issues/850
|
"\n\n\n\n\n" // https://github.com/mozilla/rust/issues/850
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -467,7 +494,8 @@ fn content_might_not_converge(code: str) -> bool {
|
||||||
|
|
||||||
fn file_might_not_converge(filename: str) -> bool {
|
fn file_might_not_converge(filename: str) -> bool {
|
||||||
let confusing_files = [
|
let confusing_files = [
|
||||||
"expr-alt.rs", // pretty-printing "(a = b) = c" vs "a = b = c" and wrapping
|
"expr-alt.rs", // pretty-printing "(a = b) = c"
|
||||||
|
// vs "a = b = c" and wrapping
|
||||||
"block-arg-in-ternary.rs", // wrapping
|
"block-arg-in-ternary.rs", // wrapping
|
||||||
"move-3-unique.rs", // 0 becomes (0), but both seem reasonable. wtf?
|
"move-3-unique.rs", // 0 becomes (0), but both seem reasonable. wtf?
|
||||||
"move-3.rs" // 0 becomes (0), but both seem reasonable. wtf?
|
"move-3.rs" // 0 becomes (0), but both seem reasonable. wtf?
|
||||||
|
@ -513,7 +541,8 @@ fn check_convergence(files: [str]) {
|
||||||
let s = @result::get(io::read_whole_file_str(file));
|
let s = @result::get(io::read_whole_file_str(file));
|
||||||
if !content_might_not_converge(*s) {
|
if !content_might_not_converge(*s) {
|
||||||
#error("pp converge: %s", file);
|
#error("pp converge: %s", file);
|
||||||
// Change from 7u to 2u once https://github.com/mozilla/rust/issues/850 is fixed
|
// Change from 7u to 2u once
|
||||||
|
// https://github.com/mozilla/rust/issues/850 is fixed
|
||||||
check_roundtrip_convergence(s, 7u);
|
check_roundtrip_convergence(s, 7u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,7 +552,8 @@ fn check_convergence(files: [str]) {
|
||||||
fn check_variants(files: [str], cx: context) {
|
fn check_variants(files: [str], cx: context) {
|
||||||
for files.each {|file|
|
for files.each {|file|
|
||||||
if cx.mode == tm_converge && file_might_not_converge(file) {
|
if cx.mode == tm_converge && file_might_not_converge(file) {
|
||||||
#error("Skipping convergence test based on file_might_not_converge");
|
#error("Skipping convergence test based on\
|
||||||
|
file_might_not_converge");
|
||||||
cont;
|
cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,16 @@
|
||||||
|
|
||||||
Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
|
Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
|
||||||
|
|
||||||
two functions, "return all edits" and "return a random edit" <-- leaning toward this model
|
two functions, "return all edits" and "return a random edit" <--
|
||||||
or
|
leaning toward this model or two functions, "return the number of
|
||||||
two functions, "return the number of possible edits" and "return edit #n"
|
possible edits" and "return edit #n"
|
||||||
|
|
||||||
It would be nice if this could be data-driven, so the two functions could share information:
|
It would be nice if this could be data-driven, so the two functions
|
||||||
|
could share information:
|
||||||
type vec_modifier = rec(fn (<T> v, uint i) -> [T] fun, uint lo, uint di);
|
type vec_modifier = rec(fn (<T> v, uint i) -> [T] fun, uint lo, uint di);
|
||||||
const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
|
const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
|
||||||
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
|
But that gives me "error: internal compiler error unimplemented consts
|
||||||
|
that's not a plain literal".
|
||||||
https://github.com/graydon/rust/issues/570
|
https://github.com/graydon/rust/issues/570
|
||||||
|
|
||||||
vec_edits is not an iter because iters might go away.
|
vec_edits is not an iter because iters might go away.
|
||||||
|
@ -47,7 +49,8 @@ fn ix(skip_low: uint, skip_high: uint, length: uint, it: block(uint)) {
|
||||||
while i + skip_high <= length { it(i); i += 1u; }
|
while i + skip_high <= length { it(i); i += 1u; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
|
// Returns a bunch of modified versions of v, some of which introduce
|
||||||
|
// new elements (borrowed from xs).
|
||||||
fn vec_edits<T: copy>(v: [T], xs: [T]) -> [[T]] {
|
fn vec_edits<T: copy>(v: [T], xs: [T]) -> [[T]] {
|
||||||
let edits: [[T]] = [];
|
let edits: [[T]] = [];
|
||||||
let Lv: uint = len(v);
|
let Lv: uint = len(v);
|
||||||
|
@ -78,7 +81,8 @@ fn vec_edits<T: copy>(v: [T], xs: [T]) -> [[T]] {
|
||||||
edits
|
edits
|
||||||
}
|
}
|
||||||
|
|
||||||
// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
|
// Would be nice if this were built in:
|
||||||
|
// https://github.com/graydon/rust/issues/424
|
||||||
fn vec_to_str(v: [int]) -> str {
|
fn vec_to_str(v: [int]) -> str {
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
let s = "[";
|
let s = "[";
|
||||||
|
|
|
@ -3,10 +3,14 @@ import std::rand;
|
||||||
import vec;
|
import vec;
|
||||||
|
|
||||||
// random uint less than n
|
// random uint less than n
|
||||||
fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n }
|
fn under(r : rand::rng, n : uint) -> uint {
|
||||||
|
assert n != 0u; r.next() as uint % n
|
||||||
|
}
|
||||||
|
|
||||||
// random choice from a vec
|
// random choice from a vec
|
||||||
fn choice<T: copy>(r : rand::rng, v : [T]) -> T { assert vec::len(v) != 0u; v[under(r, vec::len(v))] }
|
fn choice<T: copy>(r : rand::rng, v : [T]) -> T {
|
||||||
|
assert vec::len(v) != 0u; v[under(r, vec::len(v))]
|
||||||
|
}
|
||||||
|
|
||||||
// 1 in n chance of being true
|
// 1 in n chance of being true
|
||||||
fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u }
|
fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u }
|
||||||
|
|
|
@ -48,7 +48,7 @@ Options:
|
||||||
--out-dir <dir> Write output to compiler-chosen filename in <dir>
|
--out-dir <dir> Write output to compiler-chosen filename in <dir>
|
||||||
--parse-only Parse only; do not compile, assemble, or link
|
--parse-only Parse only; do not compile, assemble, or link
|
||||||
--pretty [type] Pretty-print the input instead of compiling;
|
--pretty [type] Pretty-print the input instead of compiling;
|
||||||
valid types are: normal (un-annotated source),
|
valid types are: normal (un-annotated source),
|
||||||
expanded (crates expanded), typed (crates expanded,
|
expanded (crates expanded), typed (crates expanded,
|
||||||
with type annotations), or identified (fully
|
with type annotations), or identified (fully
|
||||||
parenthesized, AST nodes and blocks with IDs)
|
parenthesized, AST nodes and blocks with IDs)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue