(CommandList children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_EqualTilde left: {(DQ ($ VSub_Name '$BASH_VERSION'))} right: {(Lit_Other '^') (3)} ) ) terminator: <Op_Semi ';'> ) ] action: [(C {(echo)} {(SQ <'quinedb requires bash 4!'>)}) (C {(exit)} {(1)})] spids: [16777215 20] ) ] spids: [16777215 34] ) (Assignment keyword: Assign_Declare flags: [-A] pairs: [(assign_pair lhs:(LhsName name:db) op:Equal spids:[41])] spids: [37] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:db) op:Equal rhs:{(ArrayLiteralPart)} spids:[44])] spids: [44] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:PREAMBLE) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (SimpleCommand words: [{(cat)}] redirects: [ (HereDoc op_id: Redir_DLess fd: 16777215 body: {('#!/usr/bin/env bash\n') ('\n') ('if [[ "$BASH_VERSION" =~ ^3 ]]; then\n') (" echo 'quinedb requires bash 4!'\n") (' exit 1\n') ('fi\n') ('\n') ('declare -A db\n') } do_expansion: False here_end: EOF was_filled: True spids: [54] ) ] ) ] ) left_token: <Left_CommandSub '$('> spids: [51 59] ) } spids: [50] ) ] spids: [50] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:POSTAMBLE) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (SimpleCommand words: [{(cat)}] redirects: [ (HereDoc op_id: Redir_DLess fd: 16777215 body: {('pr_str () {\n') (' printf "%q" "$1"\n') ('}\n') ('\n') ('case "$1" in\n') (' "get")\n') (' if [ ${db["$2"]+_} ]; then\n') (' v=${db["$2"]}\n') (' echo "$(pr_str "$v")" >&2\n') (' fi\n') (' ;;\n') (' "set")\n') (' db["$2"]="$3"\n') (" echo 'OK' >&2\n") (' ;;\n') (' "delete")\n') (' unset db["$2"]\n') (" echo 'OK' >&2\n") (' ;;\n') (' "keys")\n') (' for k in "${!db[@]}"; do echo "$(pr_str "$k")"; done >&2\n') (' ;;\n') (' *)\n') ( ' echo "USAGE: quinedb [get k | set k v | delete k | keys]" >&2\n' ) (' ;;\n') ('esac\n') ('\n') ('# print self\n') ('\n') ('print_db(){\n') (' echo "db=("\n') (' i=0\n') (' for k in "${!db[@]}"; do\n') (' escaped_keys[$i]=$(pr_str "$k")\n') (' i=$((i+1))\n') (' done\n') ('\n') (' # sort the keys for deterministic printing\n') ( " IFS=$'\\n' sorted=($(for l in ${escaped_keys[@]}; do echo $l; done | sort))\n" ) (' unset IFS\n') ('\n') (' for k in "${sorted[@]}"; do\n') (' unescaped=$(eval "echo $k")\n') (' v=${db["$unescaped"]}\n') (' echo " [$k]=$(pr_str "$v")"\n') (' done\n') (' echo ")"\n') ('}\n') ('\n') ('echo "$PREAMBLE"; echo\n') ('print_db; echo\n') ("echo 'PREAMBLE=$(cat <<'\\'EOF\\'\n") ('echo "$PREAMBLE"\n') ('echo EOF\n') ('echo \\); echo\n') ("echo 'POSTAMBLE=$(cat <<'\\'EOF\\'\n") ('echo "$POSTAMBLE"\n') ('echo EOF\n') ('echo \\); echo\n') ('echo "$POSTAMBLE"\n') } do_expansion: False here_end: EOF was_filled: True spids: [66] ) ] ) ] ) left_token: <Left_CommandSub '$('> spids: [63 71] ) } spids: [62] ) ] spids: [62] ) (FuncDef name: pr_str body: (BraceGroup children: [(C {(printf)} {(DQ ('%q'))} {(DQ ($ VSub_Number '$1'))})] spids: [79] ) spids: [74 78] ) (Case to_match: {(DQ ($ VSub_Number '$1'))} arms: [ (case_arm pat_list: [{(DQ (get))}] action: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other '[')} { (BracedVarSub token: <VSub_Name db> bracket_op: (ArrayIndex expr:(ArithWord w:{(DQ ($ VSub_Number '$2'))})) suffix_op: (StringUnary op_id:VTest_Plus arg_word:{(_)}) spids: [114 123] ) } {(Lit_Other ']')} ) terminator: <Op_Semi ';'> ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:v) op: Equal rhs: { (BracedVarSub token: <VSub_Name db> bracket_op: (ArrayIndex expr:(ArithWord w:{(DQ ($ VSub_Number '$2'))})) spids: [132 139] ) } spids: [131] ) ] spids: [131] ) (SimpleCommand words: [ {(echo)} { (DQ (CommandSubPart command_list: (CommandList children: [(C {(pr_str)} {(DQ ($ VSub_Name '$v'))})] ) left_token: <Left_CommandSub '$('> spids: [145 151] ) ) } ] redirects: [(Redir op_id:Redir_GreatAnd fd:16777215 arg_word:{(2)} spids:[154])] ) ] spids: [16777215 128] ) ] spids: [16777215 158] ) ] spids: [105 107 161 16777215] ) (case_arm pat_list: [{(DQ (set))}] action: [ (C {(db) (Lit_Other '[') (DQ ($ VSub_Number '$2')) (Lit_Other ']') (Lit_Other '=') (DQ ($ VSub_Number '$3')) } ) (SimpleCommand words: [{(echo)} {(SQ <OK>)}] redirects: [(Redir op_id:Redir_GreatAnd fd:16777215 arg_word:{(2)} spids:[188])] ) ] spids: [165 167 192 16777215] ) (case_arm pat_list: [{(DQ (delete))}] action: [ (C {(unset)} {(db) (Lit_Other '[') (DQ ($ VSub_Number '$2')) (Lit_Other ']')}) (SimpleCommand words: [{(echo)} {(SQ <OK>)}] redirects: [(Redir op_id:Redir_GreatAnd fd:16777215 arg_word:{(2)} spids:[217])] ) ] spids: [196 198 221 16777215] ) (case_arm pat_list: [{(DQ (keys))}] action: [ (ForEach iter_name: k iter_words: [ { (DQ (BracedVarSub token: <VSub_Name db> prefix_op: VSub_Bang bracket_op: (WholeArray op_id:Lit_At) spids: [237 243] ) ) } ] do_arg_iter: False body: (DoGroup children: [ (Sentence child: (C {(echo)} { (DQ (CommandSubPart command_list: (CommandList children: [(C {(pr_str)} {(DQ ($ VSub_Name '$k'))})] ) left_token: <Left_CommandSub '$('> spids: [252 258] ) ) } ) terminator: <Op_Semi ';'> ) ] spids: [247 262] ) redirects: [(Redir op_id:Redir_GreatAnd fd:16777215 arg_word:{(2)} spids:[264])] spids: [235 245] ) ] spids: [225 227 268 16777215] ) (case_arm pat_list: [{(Lit_Other '*')}] action: [ (SimpleCommand words: [{(echo)} {(DQ ('USAGE: quinedb [get k | set k v | delete k | keys]'))}] redirects: [(Redir op_id:Redir_GreatAnd fd:16777215 arg_word:{(2)} spids:[281])] ) ] spids: [271 272 285 16777215] ) ] spids: [95 101 287] ) (FuncDef name: print_db body: (BraceGroup children: [ (C {(echo)} {(DQ ('db=('))}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:i) op:Equal rhs:{(0)} spids:[307])] spids: [307] ) (ForEach iter_name: k iter_words: [ { (DQ (BracedVarSub token: <VSub_Name db> prefix_op: VSub_Bang bracket_op: (WholeArray op_id:Lit_At) spids: [318 324] ) ) } ] do_arg_iter: False body: (DoGroup children: [ (C {(escaped_keys) (Lit_Other '[') ($ VSub_Name '$i') (Lit_Other ']') (Lit_Other '=') (CommandSubPart command_list: (CommandList children: [(C {(pr_str)} {(DQ ($ VSub_Name '$k'))})] ) left_token: <Left_CommandSub '$('> spids: [336 342] ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:i) op: Equal rhs: { (ArithSubPart anode: (ArithBinary op_id: Arith_Plus left: (ArithVarRef name:i) right: (ArithWord w:{(Lit_Digits 1)}) ) spids: [346 351] ) } spids: [345] ) ] spids: [345] ) ] spids: [328 354] ) spids: [316 326] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:IFS) op: Equal rhs: {(SQ <Lit_EscapedChar '\\n'>)} spids: [362] ) (assign_pair lhs: (LhsName name:sorted) op: Equal rhs: { (ArrayLiteralPart words: [ { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (ForEach iter_name: l iter_words: [ { (BracedVarSub token: <VSub_Name escaped_keys> bracket_op: (WholeArray op_id:Lit_At) spids: [376 381] ) } ] do_arg_iter: False body: (DoGroup children: [ (Sentence child: (C {(echo)} {($ VSub_Name '$l')}) terminator: <Op_Semi ';'> ) ] spids: [384 391] ) spids: [375 382] ) (C {(sort)}) ] negated: False ) ] ) left_token: <Left_CommandSub '$('> spids: [369 396] ) } ] ) } spids: [367] ) ] spids: [362] ) (C {(unset)} {(IFS)}) (ForEach iter_name: k iter_words: [ { (DQ (BracedVarSub token: <VSub_Name sorted> bracket_op: (WholeArray op_id:Lit_At) spids: [413 418] ) ) } ] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:unescaped) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(eval)} {(DQ ('echo ') ($ VSub_Name '$k'))})] ) left_token: <Left_CommandSub '$('> spids: [426 433] ) } spids: [425] ) ] spids: [425] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:v) op: Equal rhs: { (BracedVarSub token: <VSub_Name db> bracket_op: (ArrayIndex expr: (ArithWord w:{(DQ ($ VSub_Name '$unescaped'))}) ) spids: [437 444] ) } spids: [436] ) ] spids: [436] ) (C {(echo)} { (DQ (' [') ($ VSub_Name '$k') (']=') (CommandSubPart command_list: (CommandList children: [(C {(pr_str)} {(DQ ($ VSub_Name '$v'))})] ) left_token: <Left_CommandSub '$('> spids: [453 459] ) ) } ) ] spids: [422 463] ) spids: [411 420] ) (C {(echo)} {(DQ (')'))}) ] spids: [297] ) spids: [294 297] ) (Sentence child:(C {(echo)} {(DQ ($ VSub_Name '$PREAMBLE'))}) terminator:<Op_Semi ';'>) (C {(echo)}) (Sentence child:(C {(print_db)}) terminator:<Op_Semi ';'>) (C {(echo)}) (C {(echo)} {(SQ <'PREAMBLE=$(cat <<'>) (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) (EOF) (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) } ) (C {(echo)} {(DQ ($ VSub_Name '$PREAMBLE'))}) (C {(echo)} {(EOF)}) (Sentence child: (C {(echo)} {(EscapedLiteralPart token:<Lit_EscapedChar '\\)'>)}) terminator: <Op_Semi ';'> ) (C {(echo)}) (C {(echo)} {(SQ <'POSTAMBLE=$(cat <<'>) (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) (EOF) (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) } ) (C {(echo)} {(DQ ($ VSub_Name '$POSTAMBLE'))}) (C {(echo)} {(EOF)}) (Sentence child: (C {(echo)} {(EscapedLiteralPart token:<Lit_EscapedChar '\\)'>)}) terminator: <Op_Semi ';'> ) (C {(echo)}) (C {(echo)} {(DQ ($ VSub_Name '$POSTAMBLE'))}) ] )