#!/bin/bash # If this file has already been sourced, just return test $(ENVIRONMENT_SH+isset)TODO && return declare -g ENVIRONMENT_SH = 'true' # # Environtments are stored as a list of lists # Each list is a "call stack", and popped from the list of lists when the current scope is exited # Each list is of the form # (name-1 variable-token-1 ... name-N variable-token-N) # Where: # name is the name of the variable in the environment # variable-key is the token to lookup a value using the variable:: api # source ${BASH_SOURCE%/*}/common.sh source ${BASH_SOURCE%/*}/variables.sh source ${BASH_SOURCE%/*}/variables.arraylist.sh source ${BASH_SOURCE%/*}/variables.linkedlist.sh source ${BASH_SOURCE%/*}/variables.stack.sh source ${BASH_SOURCE%/*}/variables.queue.sh sourceTODO ${BASH_SOURCE%/*}/variables.map.sh declare -g ENVIRONMENT_DEBUG = '0' # TODO: This needs to use a LinkedList implementation for the base list of scopes # Each scope, on the other hand, should be a Map # # environment::new # # Creates a brand new environment # Generally will only be called once at the setup of the interpreter # # Returns: The variable-token for the newly created environment # proc environment::new { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::new $(@)" ; } variable::LinkedList::new ; global env := $(RESULT) variable::Map::new variable::LinkedList::prepend $(env) $(RESULT) } # # environment::addScope # # Adds a new scope to the to the environment # # Returns: The same environment variable-token that was passed in # proc environment::pushScope { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::pushScope $(@)" ; }TODO declare env = $(1) variable::Map::new variable::LinkedList::prepend $(env) $(RESULT) global RESULT := $(RESULT) } # # environment::popScope # # Removes the top level environment from the environment list # TODO: Need better names to distinguish "a list of environment lists" and # "a list of name value-token pairs" # # Returns: The same environment variable-token that was passed in # proc environment::popScope { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::popScope $(@)" ; } variable::LinkedList::rest $1 global RESULT := $(RESULT) } # # environment::hasValue # # Returns 0 if the key in question exists in the environment # proc environment::hasValue { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::getValue $(@)" ; }TODO declare env = $(1)TODO declare name = $(2)TODO declare scope = '' variable::new String $(name)TODO ; declare keyToken = $(RESULT)TODO declare currentEnv = $(env) while ! variable::LinkedList::isEmpty_c "${currentEnv}" { variable::LinkedList::first $(currentEnv) global scope := $(RESULT) if variable::Map::containsKey_c $(scope) $(name) { return 0 } variable::LinkedList::rest $(currentEnv) global currentEnv := $RESULT } return 1 } # # environment::getValue # # Gets the value for a given key in the specified env # Error if key does not exist # proc environment::getValue { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::getValue $(@)" ; }TODO declare env = $(1)TODO declare name = $(2)TODO declare scope = '' variable::new String $(name)TODO ; declare keyToken = $(RESULT)TODO declare currentEnv = $(env) while ! variable::LinkedList::isEmpty_c "${currentEnv}" { variable::LinkedList::first $(currentEnv) global scope := $(RESULT) if variable::Map::containsKey_c $(scope) $(name) { variable::Map::get $(scope) $(name) return } variable::LinkedList::rest $(currentEnv) global currentEnv := $RESULT } variable::value $name stderr "Variable [$(name)=$(RESULT)] not found in current environment" exit 1 } # # environment::setVariable # # Sets a name/variable-token pair on the top level of the environment # # Returns 0 if the variable already existed (and was changed) # 1 if the variable is new # # proc environment::setVariable { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::setVariable $(@)" ; }TODO declare env = $(1)TODO declare keyToken = $(2)TODO declare valueToken = $(3) variable::LinkedList::first $(env)TODO declare scope = $(RESULT)TODO declare returnValue = '' if variable::Map::containsKey_c $(scope) $(keyToken) { global returnValue := '0' } else { global returnValue := '1' } variable::Map::put $(scope) $(keyToken) $(valueToken) global RESULT := ''"" return $returnValue } # # environment::setVariable # # Sets a name/variable-token pair whereever it is found in the environment list # or, if the name in question is not found, adds it to the top level # proc environment::setOrReplaceVariable { if [[ ${ENVIRONMENT_DEBUG} == 1 ]] { stderr "environment::setOrReplaceVariable $(@)" ; }TODO declare env = $(1)TODO declare keyToken = $(2)TODO declare valueToken = $(3)TODO declare scope = ''TODO declare currentEnv = $(env) while ! variable::LinkedList::isEmpty_c "${currentEnv}" { variable::LinkedList::first $(currentEnv) global scope := $(RESULT) if variable::Map::containsKey_c $(scope) $(keyToken) { variable::Map::put $(scope) $(keyToken) $(valueToken) global RESULT := ''"" return 0 } variable::LinkedList::rest $(currentEnv) global currentEnv := $RESULT } # Wasn't found, add it to the first scope in the env variable::LinkedList::first $(env) global scope := $(RESULT) variable::Map::put $(scope) $(keyToken) $(valueToken) global RESULT := ''"" return 1 } proc environment::printTODO { declare currentEnv = $(1) echo "Environment [$(currentEnv)]" while ! variable::LinkedList::isEmpty_c "${currentEnv}" { variable::LinkedList::first $(currentEnv) variable::Map::print $(RESULT) variable::LinkedList::rest $(currentEnv) global currentEnv := $RESULT } } # ====================================================== if test $0 != $BASH_SOURCE { return } variable::new String "key one" ; global key1 := $(RESULT) variable::new String "value one" ; global value1 := $(RESULT) variable::new String "key two" ; global key2 := $(RESULT) variable::new String "value two" ; global value2 := $(RESULT) variable::new String "key three" ; global key3 := $(RESULT) variable::new String "value three" ; global value3 := $(RESULT) variable::new String "no such key" ; global keyUnknown := $(RESULT)TODO declare env1 = ''TODO declare env2 = ''TODO declare env3 = '' environment::new ; global env1 := $(RESULT) environment::setVariable $(env1) $key1 $value1 # Check that we can get the value out environment::getValue $(env1) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value one" $(RESULT) "Single variable" environment::setVariable $(env1) $key2 $value2 # Check that we can get the previously existing key:value out environment::getValue $(env1) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value one" $(RESULT) "Multiple variables, first" # And that we can get the new value out environment::getValue $(env1) $key2 ; \ variable::value $(RESULT) ; \ assert::equals "value two" $(RESULT) "Multiple variables, second" # # Multiple scope tests / set # environment::new ; global env1 := $(RESULT) environment::setVariable $(env1) $key1 $value1 environment::pushScope $(env1) ; global env2 := $(RESULT) environment::setVariable $(env2) $key2 $value2 # Make sure we can get the new value out environment::getValue $(env2) $key2 ; \ variable::value $(RESULT) ; \ assert::equals "value two" $(RESULT) "Second scope" # And a variable from the original scope environment::getValue $(env2) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value one" $(RESULT) "Variable from first scope" # Pop off the second scope environment::popScope $(env2) ; global env3 := $(RESULT) # and make sure a variable from the first scope is still there environment::getValue $(env3) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value one" $(RESULT) "Variable from first scope post pop" # and the variable from the second scope is not environment::hasValue $(env3) $key2 ; \ assert::equals 1 $Status "Variable from second scope after we popped it" # # Multiple scope tests / setOrReplace # environment::new ; global env1 := $(RESULT) environment::setOrReplaceVariable $(env1) $key1 $value1 environment::pushScope $(env1) ; global env2 := $(RESULT) environment::setOrReplaceVariable $(env2) $key2 $value2 environment::setOrReplaceVariable $(env2) $key1 $value3 # Make sure we can get the new value out environment::getValue $(env2) $key2 ; \ variable::value $(RESULT) ; \ assert::equals "value two" $(RESULT) "Second scope" # And a variable from the original scope environment::getValue $(env2) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value three" $(RESULT) "Variable from first scope" # Pop off the second scope environment::popScope $(env2) ; global env3 := $(RESULT) # and make sure a variable from the first scope is still there (new value) environment::getValue $(env3) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value three" $(RESULT) "Variable from first scope post pop" # and the variable from the second scope is not environment::hasValue $(env3) $key2 ; \ assert::equals 1 $Status "Variable from second scope after we popped it" # # Second scope, [set] value of variable, then make sure the original env has the old value # environment::new ; global env1 := $RESULT environment::setVariable $env1 $key1 $value1 environment::pushScope $(env1) ; global env2 := $RESULT environment::setVariable $(env2) $key1 $value2 environment::getValue $(env1) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value one" $(RESULT) "setVariable, original env" environment::getValue $(env2) $key1 ; \ variable::value $(RESULT) ; \ assert::equals "value two" $(RESULT) "setVariable, new env" # # # assert::report if test $(1+isset) && test $1 == "debug" { variable::printMetadata } (CommandList children: [ (AndOr children: [ (C {(Lit_Other "[")} { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Plus arg_word:{(isset)}) spids: [9 13] ) } {(Lit_Other "]")} ) (ControlFlow token:) ] op_id: Op_DAmp ) (Assignment keyword: Assign_Declare flags: ["'-g'"] pairs: [(assign_pair lhs:(LhsName name:ENVIRONMENT_SH) op:Equal rhs:{(true)} spids:[25])] spids: [21] ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [59 64] ) (/common.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [69 74] ) (/variables.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [79 84] ) (/variables.arraylist.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [89 94] ) (/variables.linkedlist.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [99 104] ) (/variables.stack.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [109 114] ) (/variables.queue.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [119 124] ) (/variables.map.sh) } ) (Assignment keyword: Assign_Declare flags: ["'-g'"] pairs: [(assign_pair lhs:(LhsName name:ENVIRONMENT_DEBUG) op:Equal rhs:{(0)} spids:[133])] spids: [129] ) (FuncDef name: "environment::new" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::new ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 195] ) ] spids: [-1 208] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (new) } ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [222] ) ] spids: [222] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (new)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (prepend) } {(DQ (${ VSub_Name env))} {(DQ (${ VSub_Name RESULT))} ) ] spids: [177] ) spids: [168 176] ) (FuncDef name: "environment::pushScope" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::pushScope ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 311] ) ] spids: [-1 324] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [330] ) ] spids: [328] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (new)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (prepend) } {(DQ (${ VSub_Name env))} {(DQ (${ VSub_Name RESULT))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [370] ) ] spids: [370] ) ] spids: [293] ) spids: [284 292] ) (FuncDef name: "environment::popScope" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::popScope ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 434] ) ] spids: [-1 447] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ ($ VSub_Number "$1"))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [464] ) ] spids: [464] ) ] spids: [416] ) spids: [407 415] ) (FuncDef name: "environment::hasValue" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::getValue ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 516] ) ] spids: [-1 529] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [535] ) ] spids: [533] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:name) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [545] ) ] spids: [543] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:scope) op:Equal spids:[555])] spids: [553] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ (${ VSub_Name name))} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:keyToken) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [576] ) ] spids: [574] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ (${ VSub_Name env))} spids: [587] ) ] spids: [585] ) (While cond: [ (Sentence child: (Pipeline children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (isEmpty_c) } {(DQ (${ VSub_Name currentEnv))} ) ] negated: True ) terminator: ) ] body: (DoGroup children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:scope) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [633] ) ] spids: [633] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (containsKey_c) } {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name name))} ) terminator: ) ] action: [(ControlFlow token: arg_word:{(0)})] spids: [-1 665] ) ] spids: [-1 673] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ ($ VSub_Name "$RESULT"))} spids: [692] ) ] spids: [692] ) ] spids: [615 698] ) ) (ControlFlow token: arg_word:{(1)}) ] spids: [498] ) spids: [489 497] ) (FuncDef name: "environment::getValue" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::getValue ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 754] ) ] spids: [-1 767] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [773] ) ] spids: [771] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:name) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [783] ) ] spids: [781] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:scope) op:Equal spids:[793])] spids: [791] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ (${ VSub_Name name))} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:keyToken) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [814] ) ] spids: [812] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ (${ VSub_Name env))} spids: [825] ) ] spids: [823] ) (While cond: [ (Sentence child: (Pipeline children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (isEmpty_c) } {(DQ (${ VSub_Name currentEnv))} ) ] negated: True ) terminator: ) ] body: (DoGroup children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:scope) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [871] ) ] spids: [871] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (containsKey_c) } {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name name))} ) terminator: ) ] action: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (get) } {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name name))} ) (ControlFlow token: ) ] spids: [-1 903] ) ] spids: [-1 930] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ ($ VSub_Name "$RESULT"))} spids: [949] ) ] spids: [949] ) ] spids: [853 955] ) ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {($ VSub_Name "$name")}) (C {(stderr)} { (DQ ("Variable [") (${ VSub_Name name) ("=") (${ VSub_Name RESULT) ("] not found in current environment") ) } ) (C {(exit)} {(1)}) ] spids: [736] ) spids: [727 735] ) (FuncDef name: "environment::setVariable" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::setVariable ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 1043] ) ] spids: [-1 1056] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [1062] ) ] spids: [1060] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:keyToken) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [1072] ) ] spids: [1070] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:valueToken) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [1082] ) ] spids: [1080] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name env))} ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:scope) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [1108] ) ] spids: [1106] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:returnValue) op:Equal spids:[1118])] spids: [1116] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (containsKey_c) } {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name keyToken))} ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:returnValue) op: Equal rhs: {(0)} spids: [1149] ) ] spids: [1149] ) ] spids: [-1 1146] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:returnValue) op: Equal rhs: {(1)} spids: [1156] ) ] spids: [1156] ) ] spids: [1153 1160] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (put)} {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name keyToken))} {(DQ (${ VSub_Name valueToken))} ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:RESULT) op:Equal rhs:{(DQ )} spids:[1191])] spids: [1191] ) (ControlFlow token: arg_word: {($ VSub_Name "$returnValue")} ) ] spids: [1025] ) spids: [1016 1024] ) (FuncDef name: "environment::setOrReplaceVariable" body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(${ VSub_Name ENVIRONMENT_DEBUG)} right: {(1)} ) ) terminator: ) ] action: [ (Sentence child: (C {(stderr)} {(DQ ("environment::setOrReplaceVariable ") (${ VSub_At "@"))}) terminator: ) ] spids: [-1 1249] ) ] spids: [-1 1262] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [1268] ) ] spids: [1266] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:keyToken) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [1278] ) ] spids: [1276] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:valueToken) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [1288] ) ] spids: [1286] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:scope) op:Equal spids:[1298])] spids: [1296] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ (${ VSub_Name env))} spids: [1304] ) ] spids: [1302] ) (While cond: [ (Sentence child: (Pipeline children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (isEmpty_c) } {(DQ (${ VSub_Name currentEnv))} ) ] negated: True ) terminator: ) ] body: (DoGroup children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:scope) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [1350] ) ] spids: [1350] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (containsKey_c) } {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name keyToken))} ) terminator: ) ] action: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (put) } {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name keyToken))} {(DQ (${ VSub_Name valueToken))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ )} spids: [1412] ) ] spids: [1412] ) (ControlFlow token: arg_word: {(0)} ) ] spids: [-1 1382] ) ] spids: [-1 1422] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ ($ VSub_Name "$RESULT"))} spids: [1441] ) ] spids: [1441] ) ] spids: [1332 1447] ) ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name env))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:scope) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [1470] ) ] spids: [1470] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (put)} {(DQ (${ VSub_Name scope))} {(DQ (${ VSub_Name keyToken))} {(DQ (${ VSub_Name valueToken))} ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:RESULT) op:Equal rhs:{(DQ )} spids:[1505])] spids: [1505] ) (ControlFlow token: arg_word:{(1)}) ] spids: [1231] ) spids: [1222 1230] ) (FuncDef name: "environment::print" body: (BraceGroup children: [ (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [1531] ) ] spids: [1529] ) (C {(echo)} {(DQ ("Environment [") (${ VSub_Name currentEnv) ("]"))}) (While cond: [ (Sentence child: (Pipeline children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (isEmpty_c) } {(DQ (${ VSub_Name currentEnv))} ) ] negated: True ) terminator: ) ] body: (DoGroup children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name currentEnv))} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (Map) (Lit_Other ":") (Lit_Other ":") (print) } {(DQ (${ VSub_Name RESULT))} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ (${ VSub_Name currentEnv))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:currentEnv) op: Equal rhs: {(DQ ($ VSub_Name "$RESULT"))} spids: [1621] ) ] spids: [1621] ) ] spids: [1572 1627] ) ) ] spids: [1526] ) spids: [1517 1525] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {($ VSub_Number "$0")} {(KW_Bang "!") (Lit_Other "=")} {($ VSub_Name "$BASH_SOURCE")} {(Lit_Other "]")} ) terminator: ) ] action: [(ControlFlow token:)] spids: [-1 1649] ) ] spids: [-1 1654] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("key one"))}) terminator: ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:key1) op:Equal rhs:{(${ VSub_Name RESULT)} spids:[1670])] spids: [1670] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("value one"))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:value1) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [1688] ) ] spids: [1688] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("key two"))}) terminator: ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:key2) op:Equal rhs:{(${ VSub_Name RESULT)} spids:[1706])] spids: [1706] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("value two"))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:value2) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [1724] ) ] spids: [1724] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("key three"))}) terminator: ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:key3) op:Equal rhs:{(${ VSub_Name RESULT)} spids:[1742])] spids: [1742] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("value three"))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:value3) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [1760] ) ] spids: [1760] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (new)} {(String)} {(DQ ("no such key"))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:keyUnknown) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [1778] ) ] spids: [1778] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:env1) op:Equal spids:[1785])] spids: [1783] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:env2) op:Equal spids:[1789])] spids: [1787] ) (Assignment keyword: Assign_Declare pairs: [(assign_pair lhs:(LhsName name:env3) op:Equal spids:[1793])] spids: [1791] ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (new)}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env1) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [1803] ) ] spids: [1803] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key1")} {($ VSub_Name "$value1")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value one"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Single variable"))} ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key2")} {($ VSub_Name "$value2")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value one"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Multiple variables, first"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key2")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value two"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Multiple variables, second"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (new)}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env1) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [2023] ) ] spids: [2023] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key1")} {($ VSub_Name "$value1")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (pushScope)} {(DQ (${ VSub_Name env1))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env2) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [2058] ) ] spids: [2058] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key2")} {($ VSub_Name "$value2")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key2")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value two"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Second scope"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value one"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Variable from first scope"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (popScope)} {(DQ (${ VSub_Name env2))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env3) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [2205] ) ] spids: [2205] ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env3))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value one"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Variable from first scope post pop"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (hasValue)} {(DQ (${ VSub_Name env3))} {($ VSub_Name "$key2")} ) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(1)} {($ VSub_QMark "$?")} {(DQ ("Variable from second scope after we popped it"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (new)}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env1) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [2316] ) ] spids: [2316] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setOrReplaceVariable)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key1")} {($ VSub_Name "$value1")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (pushScope)} {(DQ (${ VSub_Name env1))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env2) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [2351] ) ] spids: [2351] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setOrReplaceVariable)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key2")} {($ VSub_Name "$value2")} ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setOrReplaceVariable)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key1")} {($ VSub_Name "$value3")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key2")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value two"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Second scope"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value three"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Variable from first scope"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (popScope)} {(DQ (${ VSub_Name env2))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env3) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [2513] ) ] spids: [2513] ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env3))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value three"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("Variable from first scope post pop"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (hasValue)} {(DQ (${ VSub_Name env3))} {($ VSub_Name "$key2")} ) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(1)} {($ VSub_QMark "$?")} {(DQ ("Variable from second scope after we popped it"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (new)}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env1) op: Equal rhs: {(DQ ($ VSub_Name "$RESULT"))} spids: [2626] ) ] spids: [2626] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {($ VSub_Name "$env1")} {($ VSub_Name "$key1")} {($ VSub_Name "$value1")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (pushScope)} {(DQ (${ VSub_Name env1))}) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env2) op: Equal rhs: {(DQ ($ VSub_Name "$RESULT"))} spids: [2655] ) ] spids: [2655] ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key1")} {($ VSub_Name "$value2")} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env1))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value one"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("setVariable, original env"))} ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (getValue)} {(DQ (${ VSub_Name env2))} {($ VSub_Name "$key1")} ) terminator: ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("value two"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("setVariable, new env"))} ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (report)}) (If arms: [ (if_arm cond: [ (Sentence child: (AndOr children: [ (C {(Lit_Other "[")} { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Plus arg_word:{(isset)}) spids: [2799 2803] ) } {(Lit_Other "]")} ) (C {(Lit_Other "[")} {(DQ ($ VSub_Number "$1"))} {(Lit_Other "=") (Lit_Other "=")} {(DQ (debug))} {(Lit_Other "]")} ) ] op_id: Op_DAmp ) terminator: ) ] action: [(C {(variable) (Lit_Other ":") (Lit_Other ":") (printMetadata)})] spids: [-1 2825] ) ] spids: [-1 2834] ) ] )