#!/bin/bash # If this file has already been sourced, just return test $(SPECIALFORMS_LAMBDA_SH+true)TODO && return declare -g SPECIALFORMS_LAMBDA_SH = 'true' source ${BASH_SOURCE%/*}/common.sh source ${BASH_SOURCE%/*}/test.sh source ${BASH_SOURCE%/*}/specialforms.sh source ${BASH_SOURCE%/*}/callable.lambda.sh # # LAMBDA # (lambda formals expression expression ..._) # # A lambda expression evaluates to a procedure. The environment in effect when # the lambda expression is evaluated is remembered as part of the procedure; it # is called the closing environment. When the procedure is later called with # some arguments, the closing environment is extended by binding the variables # in the formal parameter list to fresh locations, and the locations are filled # with the arguments according to rules about to be given. The new environment # created by this process is referred to as the invocation environment. # # Once the invocation environment has been constructed, the expressions in the # body of the lambda expression are evaluated sequentially in it. This means # that the region of the variables bound by the lambda expression is all of the # expressions in the body. The result of evaluating the last expression in the # body is returned as the result of the procedure call. # # # proc evaluator::specialforms::lambdaTODO { declare env = $(1)TODO declare functionName = $(2)TODO # if declare args = $(3) # list of , ,..., variable::LinkedList::length $argsTODO ; declare -i length = $(RESULT) if [[ $length < 2 ]] { stderr "usage: (if condition true-branch false-branch)" exit 1 } variable::LinkedList::first $argsTODO ; declare formalArgs = $(RESULT) variable::LinkedList::rest $argsTODO ; declare expressions = $(RESULT) variable::Lambda::new "$(env) $(formalArgs) $(expressions)" global RESULT := $(RESULT) } # # ====================================================== if test $0 != $BASH_SOURCE { return } # # no args # (lambda () 1) # createTestEnv ; global env := $(RESULT) variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "lambda" variable::LinkedList::new ; variable::LinkedList::append $command $RESULT appendToList $command Integer 1 evaluator::eval $env $command ; global lambda := $(RESULT) variable::toSexp $(lambda) ; \ assert::equals "(lambda () 1)" $(RESULT) "(lambda () 1)" variable::Lambda::getEnv $lambda ; \ assert::equals $env $RESULT " = " # # with args # (lambda (a b c) 1) # createTestEnv ; global env := $(RESULT) variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "lambda" variable::LinkedList::new ; global argList := $(RESULT) appendToList $(argList) Identifier a Identifier b Identifier c variable::LinkedList::append $command $argList appendToList $command Integer 1 evaluator::eval $env $command ; global lambda := $(RESULT) variable::toSexp $(lambda) ; \ assert::equals "(lambda (a b c) 1)" $(RESULT) "(lambda (a b c) 1)" # # multiple commands # (lambda () x y) # createTestEnv ; global env := $(RESULT) variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "lambda" variable::LinkedList::new ; variable::LinkedList::append $command $RESULT appendToList $command Identifier x Identifier y evaluator::eval $env $command ; global lambda := $(RESULT) variable::toSexp $(lambda) ; \ assert::equals "(lambda () x y)" $(RESULT) "(lambda () x y)" # # multiple commands as lists # (lambda () (+ 1 2) (+ 2 3)) # createTestEnv ; global env := $(RESULT) variable::LinkedList::new ; global command := $(RESULT) appendToList $command Identifier "lambda" variable::LinkedList::new ; variable::LinkedList::append $command $RESULT variable::LinkedList::new ; global sc1 := $(RESULT) appendToList $sc1 Identifier + Integer 1 Integer 2 variable::LinkedList::append $command $sc1 variable::LinkedList::new ; global sc2 := $(RESULT) appendToList $sc2 Identifier + Integer 2 Integer 3 variable::LinkedList::append $command $sc2 evaluator::eval $env $command ; global lambda := $(RESULT) variable::toSexp $(lambda) ; \ assert::equals "(lambda () (+ 1 2) (+ 2 3))" $(RESULT) "(lambda () (+ 1 2) (+ 2 3))" 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_LAMBDA_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) } ) (C {(.)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [61 66] ) (/callable.lambda.sh) } ) (FuncDef name: "evaluator::specialforms::lambda" body: (BraceGroup children: [ (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [147] ) ] spids: [145] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:functionName) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [157] ) ] spids: [155] ) (Assignment keyword: Assign_Declare pairs: [ (assign_pair lhs: (LhsName name:args) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [170] ) ] spids: [168] ) (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: [198] ) ] spids: [194] ) (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: (if condition true-branch false-branch)"))}) (C {(exit)} {(1)}) ] spids: [-1 219] ) ] spids: [-1 234] ) (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:formalArgs) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [252] ) ] spids: [250] ) (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: [272] ) ] spids: [270] ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (Lambda) (Lit_Other ":") (Lit_Other ":") (new)} {(DQ (${ VSub_Name env) (" ") (${ VSub_Name formalArgs) (" ") (${ VSub_Name expressions))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [302] ) ] spids: [302] ) ] spids: [142] ) spids: [130 141] ) (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 334] ) ] spids: [-1 339] ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [358] ) ] spids: [358] ) (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: [375] ) ] spids: [375] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (lambda))}) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (new)} ) terminator: ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$RESULT")} ) (C {(appendToList)} {($ VSub_Name "$command")} {(Integer)} {(1)}) (Sentence child: (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:lambda) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [437] ) ] spids: [437] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (toSexp)} {(DQ (${ VSub_Name lambda))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("(lambda () 1)"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(lambda () 1)"))} ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (Lambda) (Lit_Other ":") (Lit_Other ":") (getEnv)} {($ VSub_Name "$lambda")} ) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {($ VSub_Name "$env")} {($ VSub_Name "$RESULT")} {(DQ (" = "))} ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [520] ) ] spids: [520] ) (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: [537] ) ] spids: [537] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (lambda))}) (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:argList) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [566] ) ] spids: [566] ) (C {(appendToList)} {(${ VSub_Name argList)} {(Identifier)} {(a)} {(Identifier)} {(b)} {(Identifier)} {(c)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$argList")} ) (C {(appendToList)} {($ VSub_Name "$command")} {(Integer)} {(1)}) (Sentence child: (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:lambda) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [622] ) ] spids: [622] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (toSexp)} {(DQ (${ VSub_Name lambda))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("(lambda (a b c) 1)"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(lambda (a b c) 1)"))} ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [678] ) ] spids: [678] ) (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: [695] ) ] spids: [695] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (lambda))}) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (new)} ) terminator: ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$RESULT")} ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(x)} {(Identifier)} {(y)}) (Sentence child: (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:lambda) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [761] ) ] spids: [761] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (toSexp)} {(DQ (${ VSub_Name lambda))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("(lambda () x y)"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(lambda () x y)"))} ) (Sentence child:(C {(createTestEnv)}) terminator:) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:env) op: Equal rhs: {(DQ (${ VSub_Name RESULT))} spids: [817] ) ] spids: [817] ) (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: [834] ) ] spids: [834] ) (C {(appendToList)} {($ VSub_Name "$command")} {(Identifier)} {(DQ (lambda))}) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (new)} ) terminator: ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$RESULT")} ) (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:sc1) op:Equal rhs:{(${ VSub_Name RESULT)} spids:[886])] spids: [886] ) (C {(appendToList)} {($ VSub_Name "$sc1")} {(Identifier)} {(Lit_Other "+")} {(Integer)} {(1)} {(Integer)} {(2)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$sc1")} ) (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:sc2) op:Equal rhs:{(${ VSub_Name RESULT)} spids:[930])] spids: [930] ) (C {(appendToList)} {($ VSub_Name "$sc2")} {(Identifier)} {(Lit_Other "+")} {(Integer)} {(2)} {(Integer)} {(3)} ) (C {(variable) (Lit_Other ":") (Lit_Other ":") (LinkedList) (Lit_Other ":") (Lit_Other ":") (append)} {($ VSub_Name "$command")} {($ VSub_Name "$sc2")} ) (Sentence child: (C {(evaluator) (Lit_Other ":") (Lit_Other ":") (eval)} {($ VSub_Name "$env")} {($ VSub_Name "$command")} ) terminator: ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:lambda) op: Equal rhs: {(${ VSub_Name RESULT)} spids: [975] ) ] spids: [975] ) (Sentence child: (C {(variable) (Lit_Other ":") (Lit_Other ":") (toSexp)} {(DQ (${ VSub_Name lambda))}) terminator: ) (C {(assert) (Lit_Other ":") (Lit_Other ":") (equals)} {(DQ ("(lambda () (+ 1 2) (+ 2 3))"))} {(DQ (${ VSub_Name RESULT))} {(DQ ("(lambda () (+ 1 2) (+ 2 3))"))} ) (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: [1028 1032] ) } {(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 1054] ) ] spids: [-1 1063] ) ] )