|
| 1 | +open Common;; |
| 2 | +open Ast;; |
| 3 | + |
| 4 | +let ident_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";; |
| 5 | +let digit_chars = "1234567890";; |
| 6 | + |
| 7 | +type scope = |
| 8 | + SCOPE_crate of crate |
| 9 | + | SCOPE_mod_item of (ident * mod_item) |
| 10 | + | SCOPE_block of block |
| 11 | + | SCOPE_anon |
| 12 | +;; |
| 13 | + |
| 14 | +type ctxt = |
| 15 | + { |
| 16 | + ctxt_scopes: scope Stack.t; |
| 17 | + ctxt_node_counter: int ref; |
| 18 | + ctxt_sess: Session.sess; |
| 19 | + } |
| 20 | + |
| 21 | +let generate_ident _ : ident = |
| 22 | + let char n = |
| 23 | + if n = 0 |
| 24 | + then '_' |
| 25 | + else ident_chars.[Random.int (String.length ident_chars)] |
| 26 | + in |
| 27 | + let i = 3 + (Random.int 10) in |
| 28 | + let s = String.create i in |
| 29 | + for j = 0 to (i-1) |
| 30 | + do |
| 31 | + s.[j] <- char j |
| 32 | + done; |
| 33 | + s |
| 34 | +;; |
| 35 | + |
| 36 | +let wrap (n:'a) (cx:ctxt) : 'a identified = |
| 37 | + incr cx.ctxt_node_counter; |
| 38 | + { node = n; id = Node (!(cx.ctxt_node_counter)) } |
| 39 | +;; |
| 40 | + |
| 41 | +let generate_in (scope:scope) (fn:(ctxt -> 'a)) (cx:ctxt) : 'a = |
| 42 | + Stack.push scope cx.ctxt_scopes; |
| 43 | + let x = fn cx in |
| 44 | + ignore (Stack.pop cx.ctxt_scopes); |
| 45 | + x |
| 46 | +;; |
| 47 | + |
| 48 | +let generate_some (fn:(ctxt -> 'a)) (cx:ctxt) : 'a array = |
| 49 | + let root_count = cx.ctxt_sess.Session.sess_fuzz_item_count in |
| 50 | + let depth = Stack.length cx.ctxt_scopes in |
| 51 | + if depth >= root_count |
| 52 | + then [| |] |
| 53 | + else |
| 54 | + Array.init (1 + (Random.int (root_count - depth))) |
| 55 | + (fun _ -> fn cx) |
| 56 | +;; |
| 57 | + |
| 58 | +let rec generate_ty (cx:ctxt) : ty = |
| 59 | + let subty _ = |
| 60 | + generate_in SCOPE_anon |
| 61 | + generate_ty cx |
| 62 | + in |
| 63 | + match Random.int (if Random.bool() then 10 else 17) with |
| 64 | + 0 -> TY_nil |
| 65 | + | 1 -> TY_bool |
| 66 | + |
| 67 | + | 2 -> TY_mach TY_u8 |
| 68 | + | 3 -> TY_mach TY_u32 |
| 69 | + |
| 70 | + | 4 -> TY_mach TY_i8 |
| 71 | + | 5 -> TY_mach TY_i32 |
| 72 | + |
| 73 | + | 6 -> TY_int |
| 74 | + | 7 -> TY_uint |
| 75 | + | 8 -> TY_char |
| 76 | + | 9 -> TY_str |
| 77 | + |
| 78 | + | 10 -> TY_tup (generate_in SCOPE_anon |
| 79 | + (generate_some |
| 80 | + generate_ty) cx) |
| 81 | + | 11 -> TY_vec (subty()) |
| 82 | + | 12 -> |
| 83 | + let generate_elt cx = |
| 84 | + (generate_ident cx, generate_ty cx) |
| 85 | + in |
| 86 | + TY_rec (generate_in SCOPE_anon |
| 87 | + (generate_some generate_elt) cx) |
| 88 | + |
| 89 | + | 13 -> TY_chan (subty()) |
| 90 | + | 14 -> TY_port (subty()) |
| 91 | + |
| 92 | + | 15 -> TY_task |
| 93 | + |
| 94 | + | _ -> TY_box (subty()) |
| 95 | +;; |
| 96 | + |
| 97 | + |
| 98 | +let rec generate_mod_item (mis:mod_items) (cx:ctxt) : unit = |
| 99 | + let ident = generate_ident () in |
| 100 | + let decl i = wrap { decl_item = i; |
| 101 | + decl_params = [| |] } cx |
| 102 | + in |
| 103 | + let item = |
| 104 | + match Random.int 2 with |
| 105 | + 0 -> |
| 106 | + let ty = generate_ty cx in |
| 107 | + let eff = PURE in |
| 108 | + decl (MOD_ITEM_type (eff, ty)) |
| 109 | + | _ -> |
| 110 | + let mis' = Hashtbl.create 0 in |
| 111 | + let view = { view_imports = Hashtbl.create 0; |
| 112 | + view_exports = Hashtbl.create 0; } |
| 113 | + in |
| 114 | + let item = |
| 115 | + decl (MOD_ITEM_mod (view, mis')) |
| 116 | + in |
| 117 | + let scope = |
| 118 | + SCOPE_mod_item (ident, item) |
| 119 | + in |
| 120 | + ignore |
| 121 | + (generate_in scope |
| 122 | + (generate_some (generate_mod_item mis')) |
| 123 | + cx); |
| 124 | + item |
| 125 | + in |
| 126 | + Hashtbl.add mis ident item |
| 127 | +;; |
| 128 | + |
| 129 | +let fuzz (seed:int option) (sess:Session.sess) : unit = |
| 130 | + begin |
| 131 | + match seed with |
| 132 | + None -> Random.self_init () |
| 133 | + | Some s -> Random.init s |
| 134 | + end; |
| 135 | + let filename = |
| 136 | + match sess.Session.sess_out with |
| 137 | + Some o -> o |
| 138 | + | None -> |
| 139 | + match seed with |
| 140 | + None -> "fuzz.rs" |
| 141 | + | Some seed -> "fuzz-" ^ (string_of_int seed) ^ ".rs" |
| 142 | + in |
| 143 | + let out = open_out_bin filename in |
| 144 | + let ff = Format.formatter_of_out_channel out in |
| 145 | + let cx = { ctxt_scopes = Stack.create (); |
| 146 | + ctxt_node_counter = ref 0; |
| 147 | + ctxt_sess = sess } |
| 148 | + in |
| 149 | + let mis = Hashtbl.create 0 in |
| 150 | + ignore (generate_some |
| 151 | + (generate_mod_item mis) cx); |
| 152 | + fmt_mod_items ff mis; |
| 153 | + Format.pp_print_flush ff (); |
| 154 | + close_out out; |
| 155 | + exit 0 |
| 156 | +;; |
| 157 | + |
| 158 | + |
| 159 | +(* |
| 160 | + * Local Variables: |
| 161 | + * fill-column: 78; |
| 162 | + * indent-tabs-mode: nil |
| 163 | + * buffer-file-coding-system: utf-8-unix |
| 164 | + * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; |
| 165 | + * End: |
| 166 | + *) |
0 commit comments