diff --git a/contrib/lambda/lambda.TODO b/contrib/lambda/lambda.TODO new file mode 100644 index 0000000000..57fb07bb74 --- /dev/null +++ b/contrib/lambda/lambda.TODO @@ -0,0 +1,6 @@ +Lambda TODO +----------- +Change definition syntax from : to : +Documentation +Unit tests +Fix evaluation strategy to work with Y combinator \ No newline at end of file diff --git a/contrib/lambda/lambda.factor b/contrib/lambda/lambda.factor index 15ce3dbf0e..01f911df1f 100644 --- a/contrib/lambda/lambda.factor +++ b/contrib/lambda/lambda.factor @@ -1,47 +1,33 @@ #! An interpreter for lambda expressions, by Matthew Willis REQUIRES: lazy-lists ; -USING: lazy-lists io strings hashtables sequences kernel ; +USING: lazy-lists io strings hashtables sequences namespaces kernel ; IN: lambda -#! every expression has a canonical representation of this form -: bound-variables-list ( -- lazy-list ) 65 lfrom [ ch>string ] lmap ; +: bound-vars ( -- lazy-list ) 65 lfrom [ ch>string ] lmap ; -TUPLE: linterp names reps ; -: (lint>string) ( linterp expr -- linterp ) - bound-variables-list swap expr>string over dupd linterp-reps hash - ", " join ":" append swap append "=> " swap append ; +: lambda>string ( expr -- string ) + bound-vars swap expr>string ; -: update-names ( names-hash name expr -- names-hash ) - swap rot [ set-hash ] keep ; +: matching-names ( names string -- string ) + #! this inefficiently finds all names matching the + #! canonical representation of string + [ \ evaluate , \ lambda>string , , \ = , \ nip , ] [ ] make + hash-subset hash-keys ", " join "=> " swap append ": " append ; -C: linterp ( names-hash ) - #! take a names hash, and generate the reverse lookup hash from it. - #! TODO: make this really ugly code cleaner - 2dup set-linterp-names swap H{ } clone [ swap hash>alist - [ [ first ] keep second bound-variables-list swap expr>string rot - [ hash ] 2keep rot dup not [ drop rot { } swap add -rot ] - [ >r rot r> swap add -rot ] if set-hash ] each-with ] keep - swap [ set-linterp-reps ] keep ; +: lambda-print ( names expr -- names ) + lambda>string [ matching-names ] 2keep rot swap append print flush ; -: lint-read ( -- input ) - readln [ "." = ] keep swap ; +: lambda-eval ( names input -- names expr ) + lambda-parse [ first ] keep second + pick swap replace-names + [ swap rot set-hash ] 3keep evaluate nip ; -: lint-eval ( linterp input -- linterp name expr ) - lambda-parse [ first ] keep second pick linterp-names swap replace-names - evaluate ; +: lambda-boot ( -- names ) + #! load the core lambda library + H{ } clone ; -: lint>string ( linterp name expr -- linterp ) - rot linterp-names -rot [ update-names ] keep [ ] dip - (lint>string) ; +: (lambda) ( names -- names ) + readln dup "." = [ drop ] [ lambda-eval lambda-print (lambda) ] if ; -: lint-print ( linterp name expr -- linterp ) - lint>string print flush ; - -: lint-boot ( -- initial-names ) - H{ } clone ; - -: (lint) ( linterp -- linterp ) - lint-read [ drop ] [ lint-eval lint-print (lint) ] if ; - -: lint ( -- linterp ) - lint-boot (lint) ; \ No newline at end of file +: lambda ( -- names ) + lambda-boot (lambda) ; \ No newline at end of file diff --git a/contrib/lambda/test/lambda.factor b/contrib/lambda/test/lambda.factor index 52a789c604..96c27a3a09 100644 --- a/contrib/lambda/test/lambda.factor +++ b/contrib/lambda/test/lambda.factor @@ -1,12 +1,11 @@ -USING: lambda parser-combinators test kernel ; +USING: lambda test hashtables sequences kernel ; -[ "Yuuki" ] [ "Yuuki" some call variable-node-var ] unit-test -[ T{ lambda-node f "a" "b" } ] [ "( a. b )" lambda-parse ] unit-test +#! test simple parsing +[ "(A. A)" ] [ "(b.b)" lambda-parse second bound-vars swap expr>string ] unit-test -[ T{ lambda-node f "a" "c" } ] - [ "c" "b" T{ lambda-node f "a" "b" } substitute ] unit-test -[ T{ lambda-node f "a" "b" } ] - [ "c" "a" T{ lambda-node f "a" "b" } substitute ] unit-test - -[ T{ lambda-node f "b" "b" } ] - [ "((a. (c. (b. (b (a c))))) (d. d))" lambda-parse reduce ] unit-test \ No newline at end of file +#! test name replacement +[ "(A. A)" ] [ + "(b.b)" lambda-parse second "OK" H{ } clone [ set-hash ] keep + "OK" lambda-parse second replace-names bound-vars + swap expr>string + ] unit-test \ No newline at end of file