#!/bin/bash # If this file has already been sourced, just return test $(SPECIALFORMS_IF_SH+true)TODO && return declare -g SPECIALFORMS_IF_SH = 'true' source ${BASH_SOURCE%/*}/common.sh source ${BASH_SOURCE%/*}/test.sh source ${BASH_SOURCE%/*}/specialforms.sh # # IF # # Predicate, consequent, and alternative are expressions. An if expression is # evaluated as follows: first, predicate is evaluated. If it yields a true # value, then consequent is evaluated and its value is returned. Otherwise # alternative is evaluated and its value is returned. If predicate yields a # false value and no alternative is specified, then the result of the expression # is unspecified. # # An if expression evaluates either consequent or alternative, never # both. Programs should not depend on the value of an if expression that has no # alternative. # # (if (> 3 2) 'yes 'no) => yes # (if (> 2 3) 'yes 'no) => no # (if (> 3 2) # (- 3 2) # (+ 3 2)) => 1 # proc evaluator::specialforms::ifTODO { declare env = $(1)TODO declare functionName = $(2)TODO # if declare args = $(3) # list of condition, , variable::LinkedList::length $argsTODO ; declare -i length = $(RESULT) if [[ $length != 3 ]] { stderr "usage: (if condition true-branch false-branch)" exit 1 } variable::LinkedList::index $args 0TODO ; declare condition = $(RESULT) variable::LinkedList::index $args 1TODO ; declare trueBranch = $(RESULT) variable::LinkedList::index $args 2TODO ; declare falseBranch = $(RESULT) evaluator::eval $env $conditionTODO ; declare conditionResult = $(RESULT) variable::type::instanceOfOrExit $conditionResult Boolean variable::value $conditionResult if [[ "true" == "${RESULT}" ]] { evaluator::eval $env $trueBranch } else { evaluator::eval $env $falseBranch } global RESULT := $(RESULT) } # # ====================================================== if test $0 != $BASH_SOURCE { return } # # TRUE # # # not using env # createTestEnv ; global env := $(RESULT) variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "if" variable::LinkedList::new ; global conditional := $(RESULT) appendToList $conditional Identifier "=" Integer 3 Integer 3 variable::LinkedList::append $command $conditional appendToList $command String yes String no evaluator::eval $env $command variable::debug $(RESULT) ; \ assert::equals "String :: yes" $(RESULT) "(if (= 3 3) 'yes 'no)" # # FALSE # createTestEnv ; global env := $(RESULT) variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "if" variable::LinkedList::new ; global conditional := $(RESULT) appendToList $conditional Identifier "=" Integer 3 Integer 4 variable::LinkedList::append $command $conditional appendToList $command String yes String no evaluator::eval $env $command variable::debug $(RESULT) ; \ assert::equals "String :: no" $(RESULT) "(if (= 3 4) 'yes 'no)" # # Evaluates result # createTestEnv ; global env := $(RESULT) setInEnv $env "v" Integer 10 variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "if" variable::LinkedList::new ; global conditional := $(RESULT) appendToList $conditional Identifier "=" Integer 3 Integer 4 variable::LinkedList::append $command $conditional appendToList $command Integer 5 Identifier v evaluator::eval $env $command variable::debug $(RESULT) ; \ assert::equals "Integer :: 10" $(RESULT) "(if (= 3 4) 'yes 'no)" 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:{(true)}) spids: [9 13] ) } {(Lit_Other "]")} ) (ControlFlow token:) ] op_id: Op_DAmp ) (Assignment keyword: Assign_Declare flags: ["'-g'"] pairs: [(assign_pair lhs:(LhsName name:SPECIALFORMS_IF_SH) op:Equal rhs:{(true)} spids:[25])] spids: [21] ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [31 36] ) (/common.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [41 46] ) (/test.sh) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [51 56] ) (/specialforms.sh) } ) (FuncDef name: "evaluator::specialforms::if" body: (BraceGroup children: [ (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [137] ) ] spids: [135] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:functionName) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [147] ) ] spids: [145] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:args) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [160] ) ] spids: [158] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (length) } {($ VSub_Name "$args")} ) terminator: ) (Assignment keyword: Assign_Declare flags: ["'-i'"] pairs: [ (assign_pair lhs: (LhsName name:length) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [188] ) ] spids: [184] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobNEqual left: {($ VSub_Name "$length")} right: {(3)} ) ) terminator: ) ] action: [ (C {(stderr)} {(DQ ("usage: (if condition true-branch false-branch)"))}) (C {(exit)} {(1)}) ] spids: [-1 209] ) ] spids: [-1 224] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (index) } {($ VSub_Name "$args")} {(0)} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:condition) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [244] ) ] spids: [242] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (index) } {($ VSub_Name "$args")} {(1)} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:trueBranch) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [266] ) ] spids: [264] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (index) } {($ VSub_Name "$args")} {(2)} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:falseBranch) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [288] ) ] spids: [286] ) (Sentence child: (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$condition")} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:conditionResult) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [308] ) ] spids: [306] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (type) (Lit_Other ":") (Lit_Other ":") (instanceOfOrExit) } {($ VSub_Name "$conditionResult")} {(Boolean)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (value)} {($ VSub_Name "$conditionResult")}) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(DQ (true))} right: {(DQ (${ VSub_Name RESULT))} ) ) terminator: ) ] action: [ (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$trueBranch")} ) ] spids: [-1 355] ) ] else_action: [ (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$falseBranch")} ) ] spids: [368 381] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [384] ) ] spids: [384] ) ] spids: [132] ) spids: [120 131] ) (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 416] ) ] spids: [-1 421] ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [446] ) ] spids: [446] ) (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:command) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [463] ) ] spids: [463] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (if))}) (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:conditional) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [491] ) ] spids: [491] ) (C {(appendToList)} {($ VSub_Name "$conditional")} {(Identifier)} {(DQ ("="))} {(Integer)} {(3)} {(Integer)} {(3)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$conditional")} ) (C {(appendToList)} {($ VSub_Name "$command")} {(String)} {(yes)} {(String)} {(no)}) (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (debug)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("String :: yes"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(if (= 3 3) 'yes 'no)"))} ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [600] ) ] spids: [600] ) (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:command) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [617] ) ] spids: [617] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (if))}) (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:conditional) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [645] ) ] spids: [645] ) (C {(appendToList)} {($ VSub_Name "$conditional")} {(Identifier)} {(DQ ("="))} {(Integer)} {(3)} {(Integer)} {(4)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$conditional")} ) (C {(appendToList)} {($ VSub_Name "$command")} {(String)} {(yes)} {(String)} {(no)}) (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (debug)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("String :: no"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(if (= 3 4) 'yes 'no)"))} ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [754] ) ] spids: [754] ) (C {(setInEnv)} {($ VSub_Name "$env")} {(DQ (v))} {(Integer)} {(10)}) (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:command) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [783] ) ] spids: [783] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (if))}) (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:conditional) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [811] ) ] spids: [811] ) (C {(appendToList)} {($ VSub_Name "$conditional")} {(Identifier)} {(DQ ("="))} {(Integer)} {(3)} {(Integer)} {(4)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$conditional")} ) (C {(appendToList)} {($ VSub_Name "$command")} {(Integer)} {(5)} {(Identifier)} {(v)}) (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (debug)} {(DQ (${ VSub_Name RESULT))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("Integer :: 10"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(if (= 3 4) 'yes 'no)"))} ) (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: [918 922] ) } {(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 944] ) ] spids: [-1 953] ) ] )