#!/bin/bash # If this file has already been sourced, just return test $(SPECIALFORMS_LET_SH+true)TODO && return declare -g SPECIALFORMS_LET_SH = 'true' source ${BASH_SOURCE%/*}/common.sh source ${BASH_SOURCE%/*}/test.sh source ${BASH_SOURCE%/*}/specialforms.sh # # LET # # The inits are evaluated in the current environment (in some unspecified order), # the variables are bound to fresh locations holding the results, the expressions # are evaluated sequentially in the extended environment, and the value of the # last expression is returned. Each binding of a variable has the expressions as # its region. # # (let ((x 2) (y 3)) # (* x y)) # proc evaluator::specialforms::letTODO { declare env = $(1)TODO declare functionName = $(2)TODO # let declare args = $(3) # list of , ,..., variable::LinkedList::length $argsTODO ; declare -i length = $(RESULT) if [[ $length < 2 ]] { stderr "usage: (let .. )" exit 1 } variable::LinkedList::first $argsTODO ; declare bindings = $(RESULT) variable::LinkedList::rest $argsTODO ; declare expressions = $(RESULT) # set values environment::pushScope $envTODO ; declare runningEnv = $(RESULT)TODO declare thisBinding = '', thisKey = '', thisValue = '', thisResult = '' while ! variable::LinkedList::isEmpty_c "${bindings}" { variable::LinkedList::first $(bindings) ; global thisBinding := $(RESULT) variable::LinkedList::rest $(bindings) ; global bindings := $(RESULT) variable::LinkedList::length $(thisBinding) if [[ "${RESULT}" != 2 ]] { stderr "let binding must have exactly 2 elements" } variable::LinkedList::index $(thisBinding) 0 ; global thisKey := $(RESULT) variable::LinkedList::index $(thisBinding) 1 ; global thisValue := $(RESULT) evaluator::eval $env $thisValue environment::setVariable $(runningEnv) $thisKey $RESULT }TODO # evaluate expressions declare currentSexp = '', currentResult = '' while ! variable::LinkedList::isEmpty_c "${expressions}" { variable::LinkedList::first $(expressions) ; global currentSexp := $(RESULT) variable::LinkedList::rest $(expressions) ; global expressions := $(RESULT) evaluator::eval $runningEnv $currentSexp global currentResult := $(RESULT) } global RESULT := $(currentResult) } # # ====================================================== if test $0 != $BASH_SOURCE { return } 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_LET_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::let" body: (BraceGroup children: [ (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [114] ) ] spids: [112] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:functionName) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [124] ) ] spids: [122] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:args) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [137] ) ] spids: [135] ) (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: [165] ) ] spids: [161] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: Redir_Less left: {($ VSub_Name "$length")} right: {(2)} ) ) terminator: ) ] action: [ (C {(stderr)} {(DQ ("usage: (let .. )"))}) (C {(exit)} {(1)}) ] spids: [-1 186] ) ] spids: [-1 201] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {($ VSub_Name "$args")} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:bindings) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [219] ) ] spids: [217] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {($ VSub_Name "$args")} ) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:expressions) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [239] ) ] spids: [237] ) (Sentence child: (C {(environment) (Lit_Other ":") (Lit_Other ":") (pushScope)} {($ VSub_Name "$env")}) terminator: ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:runningEnv) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [261] ) ] spids: [259] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs:(LhsName name:thisBinding) op:Equal spids:[271]) (assign_pair lhs:(LhsName name:thisKey) op:Equal spids:[273]) (assign_pair lhs:(LhsName name:thisValue) op:Equal spids:[275]) (assign_pair lhs:(LhsName name:thisResult) op:Equal spids:[277]) ] spids: [269] ) (While cond: [ (Sentence child: (Pipeline children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (isEmpty_c) } {(DQ (${ VSub_Name bindings))} ) ] negated: True ) terminator: ) ] body: (DoGroup children: [ (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name bindings))} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:thisBinding) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [319] ) ] spids: [319] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ (${ VSub_Name bindings))} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:bindings) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [343] ) ] spids: [343] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (length) } {(DQ (${ VSub_Name thisBinding))} ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobNEqual left: {(DQ (${ VSub_Name RESULT))} right: {(2)} ) ) terminator: ) ] action: [(C {(stderr)} {(DQ ("let binding must have exactly 2 elements"))})] spids: [-1 384] ) ] spids: [-1 394] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (index) } {(DQ (${ VSub_Name thisBinding))} {(0)} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:thisKey) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [417] ) ] spids: [417] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (index) } {(DQ (${ VSub_Name thisBinding))} {(1)} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:thisValue) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [443] ) ] spids: [443] ) (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$thisValue")} ) (C {(environment) (Lit_Other ":") (Lit_Other ":") (setVariable)} {(DQ (${ VSub_Name runningEnv))} {($ VSub_Name "$thisKey")} {($ VSub_Name "$RESULT")} ) ] spids: [300 477] ) ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs:(LhsName name:currentSexp) op:Equal spids:[487]) (assign_pair lhs:(LhsName name:currentResult) op:Equal spids:[489]) ] spids: [485] ) (While cond: [ (Sentence child: (Pipeline children: [ (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (isEmpty_c) } {(DQ (${ VSub_Name expressions))} ) ] negated: True ) terminator: ) ] body: (DoGroup children: [ (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (first) } {(DQ (${ VSub_Name expressions))} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:currentSexp) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [531] ) ] spids: [531] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (rest) } {(DQ (${ VSub_Name expressions))} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:expressions) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [553] ) ] spids: [553] ) (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$runningEnv")} {($ VSub_Name "$currentSexp")} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:currentResult) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [569] ) ] spids: [569] ) ] spids: [512 575] ) ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (${ VSub_Name currentResult))} spids: [578] ) ] spids: [578] ) ] spids: [109] ) spids: [97 108] ) (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 610] ) ] spids: [-1 615] ) (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: [632 636] ) } {(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 658] ) ] spids: [-1 667] ) ] )