├── docs ├── .gitignore ├── _config.yml ├── lib │ ├── empty.js │ ├── continuation.js │ └── pairmutator.js ├── md │ ├── EV3_README.md │ ├── README.md │ ├── GAME_README.md │ ├── README_AUXILIARY.md │ ├── README_CONTINUATION.md │ ├── README_ARRAYS.md │ ├── README_BINARYTREES.md │ ├── README_MCE.md │ ├── README_PAIRMUTATORS.md │ ├── README_STREAMS.md │ └── README_LISTS.md ├── specs │ ├── .gitignore │ ├── source_parse_tree_types.tex │ ├── source_list_library.tex │ ├── source_stream_library.tex │ ├── source_python_comments.tex │ ├── source_export.tex │ ├── source_comments.tex │ ├── source_studio_2_return.tex │ ├── source_python_integers.tex │ ├── source_object_support.tex │ ├── source_standard.tex │ ├── source_continuation.tex │ ├── source_numbers.tex │ ├── source_python_numbers.tex │ ├── source_2_stepper.tex │ ├── source_arrays.tex │ ├── source_import.tex │ ├── source_python_import.tex │ ├── Makefile │ ├── source_pair_mutators.tex │ ├── source_intro.tex │ ├── source_python_return.tex │ └── source_2_stepper_style.tex ├── images │ ├── favicon.ico │ └── sourcepower.ico ├── jsdoc │ ├── templates │ │ └── template │ │ │ ├── tmpl │ │ │ ├── example.tmpl │ │ │ ├── README.md │ │ │ ├── source.tmpl │ │ │ ├── type.tmpl │ │ │ ├── augments.tmpl │ │ │ ├── modifies.tmpl │ │ │ ├── mainpage.tmpl │ │ │ ├── examples.tmpl │ │ │ ├── returns.tmpl │ │ │ └── tutorial.tmpl │ │ │ └── static │ │ │ ├── README.md │ │ │ ├── styles │ │ │ └── README.md │ │ │ └── fonts │ │ │ ├── OpenSans-Bold-webfont.eot │ │ │ ├── OpenSans-Bold-webfont.woff │ │ │ ├── OpenSans-Light-webfont.eot │ │ │ ├── OpenSans-Italic-webfont.eot │ │ │ ├── OpenSans-Italic-webfont.woff │ │ │ ├── OpenSans-Light-webfont.woff │ │ │ ├── OpenSans-Regular-webfont.eot │ │ │ ├── OpenSans-Regular-webfont.woff │ │ │ ├── OpenSans-BoldItalic-webfont.eot │ │ │ ├── OpenSans-BoldItalic-webfont.woff │ │ │ ├── OpenSans-LightItalic-webfont.eot │ │ │ └── OpenSans-LightItalic-webfont.woff │ └── conf.json ├── language_processing.png └── language_processing.pptx ├── .husky ├── .gitignore └── pre-push ├── .node-version ├── src ├── __tests__ │ └── sicp │ │ ├── .gitignore │ │ ├── chapter1 │ │ ├── section1 │ │ │ ├── subsection1 │ │ │ │ ├── 1.js │ │ │ │ ├── 2.js │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ ├── 6.js │ │ │ │ ├── 3.js │ │ │ │ ├── 8.js │ │ │ │ ├── 10.js │ │ │ │ ├── 7.js │ │ │ │ ├── 9.js │ │ │ │ ├── 11.js │ │ │ │ ├── 12.js │ │ │ │ └── 13.js │ │ │ ├── subsection6 │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ ├── 6.js │ │ │ │ ├── 7.js │ │ │ │ ├── 9.js │ │ │ │ ├── 8.js │ │ │ │ ├── 12.js │ │ │ │ ├── 10.js │ │ │ │ ├── 11.js │ │ │ │ ├── 15.js │ │ │ │ ├── 13.js │ │ │ │ ├── 14.js │ │ │ │ ├── 17.js │ │ │ │ ├── 1.js │ │ │ │ ├── 18.js │ │ │ │ ├── 2.js │ │ │ │ ├── 16.js │ │ │ │ ├── 3.js │ │ │ │ ├── 20.js │ │ │ │ ├── 21.js │ │ │ │ └── 19.js │ │ │ ├── subsection2 │ │ │ │ ├── 1.js │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ ├── 2.js │ │ │ │ ├── 3.js │ │ │ │ ├── 8.js │ │ │ │ ├── 6.js │ │ │ │ └── 7.js │ │ │ ├── subsection3 │ │ │ │ └── 1.js │ │ │ ├── subsection4 │ │ │ │ ├── 2.js │ │ │ │ ├── 1.js │ │ │ │ ├── 3.js │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ └── 6.js │ │ │ ├── subsection8 │ │ │ │ ├── 1.js │ │ │ │ ├── 3.js │ │ │ │ ├── 4.js │ │ │ │ ├── 2.js │ │ │ │ └── 5.js │ │ │ ├── subsection5 │ │ │ │ └── 1.js │ │ │ └── subsection7 │ │ │ │ ├── 7.js │ │ │ │ ├── 9.js │ │ │ │ ├── 3.js │ │ │ │ ├── 8.js │ │ │ │ ├── 10.js │ │ │ │ ├── 11.js │ │ │ │ ├── 12.js │ │ │ │ ├── 2.js │ │ │ │ ├── 4.js │ │ │ │ ├── 1.js │ │ │ │ └── 13.js │ │ ├── section3 │ │ │ ├── subsection2 │ │ │ │ ├── 1.js │ │ │ │ ├── 13.js │ │ │ │ ├── 2.js │ │ │ │ ├── 16.js │ │ │ │ ├── 6.js │ │ │ │ ├── 5.js │ │ │ │ ├── 18.js │ │ │ │ ├── 7.js │ │ │ │ ├── 17.js │ │ │ │ ├── 11.js │ │ │ │ ├── 10.js │ │ │ │ ├── 9.js │ │ │ │ ├── 8.js │ │ │ │ ├── 3.js │ │ │ │ ├── 14.js │ │ │ │ ├── 12.js │ │ │ │ ├── 4.js │ │ │ │ └── 15.js │ │ │ ├── subsection4 │ │ │ │ ├── 6.js │ │ │ │ ├── 16.js │ │ │ │ ├── 14.js │ │ │ │ ├── 5.js │ │ │ │ ├── 7.js │ │ │ │ ├── 1.js │ │ │ │ ├── 15.js │ │ │ │ └── 2.js │ │ │ ├── subsection1 │ │ │ │ ├── 6.js │ │ │ │ ├── 1.js │ │ │ │ ├── 3.js │ │ │ │ ├── 2.js │ │ │ │ ├── 11.js │ │ │ │ ├── 5.js │ │ │ │ ├── 4.js │ │ │ │ ├── 8.js │ │ │ │ ├── 7.js │ │ │ │ ├── 10.js │ │ │ │ ├── 12.js │ │ │ │ ├── 13.js │ │ │ │ └── 9.js │ │ │ └── subsection3 │ │ │ │ ├── 11.js │ │ │ │ ├── 2.js │ │ │ │ ├── 7.js │ │ │ │ ├── 6.js │ │ │ │ └── 8.js │ │ └── section2 │ │ │ ├── subsection4 │ │ │ ├── 4.js │ │ │ ├── 1.js │ │ │ ├── 5.js │ │ │ ├── 2.js │ │ │ └── 3.js │ │ │ ├── subsection5 │ │ │ └── 1.js │ │ │ ├── subsection1 │ │ │ ├── 1.js │ │ │ ├── 5.js │ │ │ ├── 4.js │ │ │ ├── 7.js │ │ │ ├── 8.js │ │ │ ├── 9.js │ │ │ ├── 6.js │ │ │ ├── 2.js │ │ │ ├── 3.js │ │ │ └── 10.js │ │ │ ├── subsection2 │ │ │ ├── 1.js │ │ │ └── 2.js │ │ │ ├── subsection6 │ │ │ ├── 7.js │ │ │ ├── 3.js │ │ │ ├── 8.js │ │ │ ├── 1.js │ │ │ └── 2.js │ │ │ └── subsection3 │ │ │ └── 1.js │ │ ├── chapter3 │ │ ├── section1 │ │ │ ├── subsection3 │ │ │ │ ├── 8.js │ │ │ │ ├── 7.js │ │ │ │ ├── 2.js │ │ │ │ ├── 6.js │ │ │ │ ├── 3.js │ │ │ │ ├── 19.js │ │ │ │ ├── 4.js │ │ │ │ ├── 10.js │ │ │ │ ├── 5.js │ │ │ │ ├── 9.js │ │ │ │ ├── 11.js │ │ │ │ ├── 12.js │ │ │ │ ├── 1.js │ │ │ │ ├── 13.js │ │ │ │ ├── 17.js │ │ │ │ ├── 14.js │ │ │ │ └── 18.js │ │ │ └── subsection1 │ │ │ │ ├── 20.js │ │ │ │ ├── 23.js │ │ │ │ ├── 26.js │ │ │ │ ├── 21.js │ │ │ │ ├── 24.js │ │ │ │ ├── 22.js │ │ │ │ ├── 25.js │ │ │ │ ├── 28.js │ │ │ │ ├── 27.js │ │ │ │ ├── 1.js │ │ │ │ ├── 5.js │ │ │ │ ├── 7.js │ │ │ │ ├── 2.js │ │ │ │ ├── 3.js │ │ │ │ ├── 4.js │ │ │ │ ├── 8.js │ │ │ │ ├── 6.js │ │ │ │ ├── 9.js │ │ │ │ ├── 10.js │ │ │ │ ├── 11.js │ │ │ │ └── 12.js │ │ ├── section2 │ │ │ ├── subsection3 │ │ │ │ ├── 4.js │ │ │ │ ├── 1.js │ │ │ │ ├── 5.js │ │ │ │ ├── 2.js │ │ │ │ ├── 3.js │ │ │ │ ├── 6.js │ │ │ │ └── 7.js │ │ │ ├── subsection1 │ │ │ │ ├── 2.js │ │ │ │ └── 1.js │ │ │ ├── subsection2 │ │ │ │ ├── 2.js │ │ │ │ ├── 1.js │ │ │ │ └── 3.js │ │ │ └── subsection4 │ │ │ │ └── 2.js │ │ ├── section3 │ │ │ ├── subsection1 │ │ │ │ ├── 10.js │ │ │ │ ├── 14.js │ │ │ │ ├── 13.js │ │ │ │ ├── 12.js │ │ │ │ ├── 15.js │ │ │ │ ├── 1.js │ │ │ │ ├── 18.js │ │ │ │ ├── 16.js │ │ │ │ ├── 5.js │ │ │ │ ├── 3.js │ │ │ │ ├── 8.js │ │ │ │ ├── 20.js │ │ │ │ ├── 4.js │ │ │ │ ├── 7.js │ │ │ │ ├── 19.js │ │ │ │ ├── 17.js │ │ │ │ ├── 21.js │ │ │ │ ├── 11.js │ │ │ │ ├── 9.js │ │ │ │ ├── 2.js │ │ │ │ └── 6.js │ │ │ ├── subsection2 │ │ │ │ ├── 3.js │ │ │ │ ├── 7.js │ │ │ │ ├── 1.js │ │ │ │ └── 2.js │ │ │ └── subsection3 │ │ │ │ ├── 4.js │ │ │ │ ├── 9.js │ │ │ │ └── 2.js │ │ ├── section5 │ │ │ ├── subsection2 │ │ │ │ ├── 6.js │ │ │ │ ├── 19.js │ │ │ │ ├── 15.js │ │ │ │ ├── 4.js │ │ │ │ ├── 14.js │ │ │ │ ├── 18.js │ │ │ │ ├── 11.js │ │ │ │ ├── 1.js │ │ │ │ └── 9.js │ │ │ ├── subsection1 │ │ │ │ ├── 17.js │ │ │ │ ├── 4.js │ │ │ │ ├── 11.js │ │ │ │ ├── 9.js │ │ │ │ ├── 3.js │ │ │ │ └── 18.js │ │ │ ├── subsection4 │ │ │ │ └── 1.js │ │ │ └── subsection5 │ │ │ │ └── 1.js │ │ └── section4 │ │ │ ├── section4 │ │ │ ├── 1.js │ │ │ └── 2.js │ │ │ └── subsection1 │ │ │ └── 1.js │ │ ├── chapter2 │ │ ├── section2 │ │ │ ├── subsection4 │ │ │ │ ├── 1.js │ │ │ │ ├── 2.js │ │ │ │ ├── 15.js │ │ │ │ ├── 3.js │ │ │ │ ├── 5.js │ │ │ │ ├── 4.js │ │ │ │ ├── 8.js │ │ │ │ ├── 6.js │ │ │ │ ├── 11.js │ │ │ │ ├── 12.js │ │ │ │ └── 13.js │ │ │ ├── subsection2 │ │ │ │ ├── 1.js │ │ │ │ ├── 13.js │ │ │ │ ├── 17.js │ │ │ │ ├── 9.js │ │ │ │ ├── 2.js │ │ │ │ ├── 11.js │ │ │ │ ├── 12.js │ │ │ │ ├── 20.js │ │ │ │ ├── 10.js │ │ │ │ ├── 3.js │ │ │ │ ├── 21.js │ │ │ │ ├── 14.js │ │ │ │ ├── 6.js │ │ │ │ ├── 15.js │ │ │ │ ├── 26.js │ │ │ │ ├── 18.js │ │ │ │ ├── 16.js │ │ │ │ ├── 19.js │ │ │ │ ├── 22.js │ │ │ │ ├── 5.js │ │ │ │ ├── 25.js │ │ │ │ ├── 8.js │ │ │ │ ├── 24.js │ │ │ │ ├── 4.js │ │ │ │ ├── 7.js │ │ │ │ └── 23.js │ │ │ ├── subsection1 │ │ │ │ ├── 13.js │ │ │ │ ├── 31.js │ │ │ │ ├── 17.js │ │ │ │ ├── 9.js │ │ │ │ ├── 1.js │ │ │ │ ├── 3.js │ │ │ │ ├── 21.js │ │ │ │ ├── 5.js │ │ │ │ ├── 16.js │ │ │ │ ├── 18.js │ │ │ │ ├── 36.js │ │ │ │ ├── 4.js │ │ │ │ ├── 2.js │ │ │ │ ├── 6.js │ │ │ │ ├── 7.js │ │ │ │ ├── 30.js │ │ │ │ ├── 33.js │ │ │ │ ├── 22.js │ │ │ │ ├── 15.js │ │ │ │ ├── 23.js │ │ │ │ ├── 10.js │ │ │ │ ├── 32.js │ │ │ │ ├── 24.js │ │ │ │ ├── 29.js │ │ │ │ ├── 27.js │ │ │ │ ├── 8.js │ │ │ │ ├── 26.js │ │ │ │ ├── 25.js │ │ │ │ ├── 28.js │ │ │ │ ├── 11.js │ │ │ │ ├── 12.js │ │ │ │ ├── 14.js │ │ │ │ ├── 35.js │ │ │ │ ├── 20.js │ │ │ │ └── 34.js │ │ │ └── subsection3 │ │ │ │ ├── 28.js │ │ │ │ ├── 21.js │ │ │ │ ├── 20.js │ │ │ │ ├── 33.js │ │ │ │ ├── 26.js │ │ │ │ ├── 38.js │ │ │ │ ├── 30.js │ │ │ │ ├── 31.js │ │ │ │ ├── 35.js │ │ │ │ ├── 6.js │ │ │ │ ├── 10.js │ │ │ │ ├── 19.js │ │ │ │ ├── 18.js │ │ │ │ ├── 9.js │ │ │ │ ├── 3.js │ │ │ │ ├── 24.js │ │ │ │ ├── 7.js │ │ │ │ ├── 8.js │ │ │ │ ├── 11.js │ │ │ │ ├── 29.js │ │ │ │ ├── 25.js │ │ │ │ ├── 22.js │ │ │ │ ├── 37.js │ │ │ │ ├── 27.js │ │ │ │ ├── 32.js │ │ │ │ ├── 5.js │ │ │ │ ├── 4.js │ │ │ │ ├── 17.js │ │ │ │ ├── 1.js │ │ │ │ ├── 15.js │ │ │ │ └── 23.js │ │ ├── section3 │ │ │ ├── subsection1 │ │ │ │ ├── 16.js │ │ │ │ ├── 8.js │ │ │ │ ├── 9.js │ │ │ │ ├── 1.js │ │ │ │ ├── 3.js │ │ │ │ ├── 10.js │ │ │ │ ├── 11.js │ │ │ │ ├── 2.js │ │ │ │ ├── 4.js │ │ │ │ ├── 14.js │ │ │ │ ├── 15.js │ │ │ │ ├── 6.js │ │ │ │ ├── 13.js │ │ │ │ ├── 5.js │ │ │ │ ├── 12.js │ │ │ │ └── 7.js │ │ │ ├── subsection2 │ │ │ │ ├── 2.js │ │ │ │ ├── 7.js │ │ │ │ ├── 8.js │ │ │ │ ├── 10.js │ │ │ │ ├── 6.js │ │ │ │ ├── 11.js │ │ │ │ ├── 16.js │ │ │ │ ├── 9.js │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ ├── 3.js │ │ │ │ ├── 15.js │ │ │ │ └── 17.js │ │ │ ├── subsection4 │ │ │ │ ├── 8.js │ │ │ │ └── 1.js │ │ │ └── subsection3 │ │ │ │ ├── 4.js │ │ │ │ ├── 1.js │ │ │ │ ├── 6.js │ │ │ │ ├── 9.js │ │ │ │ └── 2.js │ │ ├── section1 │ │ │ ├── subsection1 │ │ │ │ ├── 2.js │ │ │ │ ├── 3.js │ │ │ │ ├── 1.js │ │ │ │ ├── 5.js │ │ │ │ ├── 6.js │ │ │ │ ├── 4.js │ │ │ │ ├── 7.js │ │ │ │ ├── 14.js │ │ │ │ ├── 9.js │ │ │ │ ├── 10.js │ │ │ │ └── 8.js │ │ │ ├── subsection3 │ │ │ │ ├── 3.js │ │ │ │ ├── 2.js │ │ │ │ └── 1.js │ │ │ ├── subsection2 │ │ │ │ └── 1.js │ │ │ └── subsection4 │ │ │ │ └── 4.js │ │ └── section4 │ │ │ ├── subsection3 │ │ │ └── 7.js │ │ │ └── subsection2 │ │ │ └── 1.js │ │ ├── chapter5 │ │ ├── section2 │ │ │ ├── section2 │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ ├── 2.js │ │ │ │ └── 3.js │ │ │ ├── subsection3 │ │ │ │ ├── 15.js │ │ │ │ ├── 4.js │ │ │ │ ├── 3.js │ │ │ │ ├── 14.js │ │ │ │ ├── 13.js │ │ │ │ ├── 12.js │ │ │ │ ├── 9.js │ │ │ │ ├── 11.js │ │ │ │ └── 2.js │ │ │ ├── subsection4 │ │ │ │ ├── 3.js │ │ │ │ └── 1.js │ │ │ └── subsection2 │ │ │ │ ├── 7.js │ │ │ │ ├── 8.js │ │ │ │ ├── 9.js │ │ │ │ ├── 1.js │ │ │ │ ├── 4.js │ │ │ │ ├── 6.js │ │ │ │ ├── 2.js │ │ │ │ └── 3.js │ │ ├── section5 │ │ │ ├── subsection6 │ │ │ │ ├── 6.js │ │ │ │ ├── 2.js │ │ │ │ ├── 3.js │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ └── 1.js │ │ │ ├── subsection5 │ │ │ │ ├── 2.js │ │ │ │ ├── 4.js │ │ │ │ ├── 5.js │ │ │ │ ├── 7.js │ │ │ │ ├── 6.js │ │ │ │ └── 1.js │ │ │ └── subsection7 │ │ │ │ ├── 8.js │ │ │ │ ├── 3.js │ │ │ │ ├── 5.js │ │ │ │ ├── 1.js │ │ │ │ ├── 9.js │ │ │ │ ├── 6.js │ │ │ │ ├── 7.js │ │ │ │ ├── 4.js │ │ │ │ └── 2.js │ │ ├── section1 │ │ │ ├── subsection4 │ │ │ │ ├── 2.js │ │ │ │ ├── 5.js │ │ │ │ ├── 1.js │ │ │ │ ├── 3.js │ │ │ │ └── 6.js │ │ │ └── subsection2 │ │ │ │ ├── 1.js │ │ │ │ └── 2.js │ │ └── section4 │ │ │ └── subsection4 │ │ │ └── 1.js │ │ └── chapter4 │ │ ├── section2 │ │ └── subsection1 │ │ │ └── 1.js │ │ ├── section1 │ │ ├── subsection5 │ │ │ └── 1.js │ │ ├── subsection7 │ │ │ └── 1.js │ │ ├── subsection6 │ │ │ ├── 2.js │ │ │ ├── 1.js │ │ │ ├── 3.js │ │ │ └── 4.js │ │ ├── subsection3 │ │ │ ├── 1.js │ │ │ ├── 5.js │ │ │ ├── 7.js │ │ │ ├── 4.js │ │ │ ├── 3.js │ │ │ └── 10.js │ │ ├── subsection2 │ │ │ ├── 3.js │ │ │ ├── 1.js │ │ │ ├── 2.js │ │ │ ├── 10.js │ │ │ └── 4.js │ │ ├── subsection4 │ │ │ ├── 5.js │ │ │ └── 4.js │ │ └── subsection1 │ │ │ ├── 11.js │ │ │ ├── 10.js │ │ │ ├── 5.js │ │ │ ├── 3.js │ │ │ ├── 4.js │ │ │ └── 12.js │ │ └── section4 │ │ └── subsection4 │ │ └── 1.js ├── editors │ └── ace │ │ └── docTooltip │ │ └── .gitignore ├── typings │ ├── astring.d.ts │ ├── escodegen.d.ts │ └── acorn-loose.d.ts ├── tracer │ ├── images │ │ └── tracer-1.png │ ├── tracer_supplementary_slides.pdf │ ├── index.ts │ ├── interface.ts │ └── nodes │ │ └── Statement │ │ └── index.ts ├── stdlib │ └── object.ts ├── repl │ ├── index.ts │ └── main.ts ├── runner │ └── types.ts ├── modules │ └── __tests__ │ │ └── moduleUtils.test.ts ├── utils │ └── makeWrapper.ts └── errors │ └── base.ts ├── .editorconfig ├── .yarnrc.yml ├── sicp_publish └── .gitignore ├── .prettierignore ├── .vscode └── settings.json ├── scripts └── publish_sicp_package.sh ├── .prettierrc ├── .gitmodules ├── .github └── dependabot.yml ├── renovate.json ├── .gitignore └── tsconfig.prod.json /docs/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 22.17.0 2 | -------------------------------------------------------------------------------- /src/__tests__/sicp/.gitignore: -------------------------------------------------------------------------------- 1 | !*.js -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal 2 | -------------------------------------------------------------------------------- /src/editors/ace/docTooltip/.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | yarn format:ci && yarn eslint 2 | -------------------------------------------------------------------------------- /src/typings/astring.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'astring' 2 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/1.js: -------------------------------------------------------------------------------- 1 | 486; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/4.js: -------------------------------------------------------------------------------- 1 | 10; -------------------------------------------------------------------------------- /src/typings/escodegen.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'escodegen' 2 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/2.js: -------------------------------------------------------------------------------- 1 | 137 + 349; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/4.js: -------------------------------------------------------------------------------- 1 | 5 * 99; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/5.js: -------------------------------------------------------------------------------- 1 | 10 / 5; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/6.js: -------------------------------------------------------------------------------- 1 | 2.7 + 10; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/5.js: -------------------------------------------------------------------------------- 1 | 5 + 3 + 4; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/6.js: -------------------------------------------------------------------------------- 1 | 9 - 1; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/7.js: -------------------------------------------------------------------------------- 1 | 6 / 2; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/8.js: -------------------------------------------------------------------------------- 1 | 25 - 20; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/3.js: -------------------------------------------------------------------------------- 1 | 1000 - 334; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/8.js: -------------------------------------------------------------------------------- 1 | 3 * 5 + 10 / 2; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/1.js: -------------------------------------------------------------------------------- 1 | const size = 2; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/9.js: -------------------------------------------------------------------------------- 1 | const a = 3; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/1.js: -------------------------------------------------------------------------------- 1 | x => x + 4; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/1.js: -------------------------------------------------------------------------------- 1 | show(heart); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/16.js: -------------------------------------------------------------------------------- 1 | " '' === '' " -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/10.js: -------------------------------------------------------------------------------- 1 | 3 / 5 * 2 - 4 + 3; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/7.js: -------------------------------------------------------------------------------- 1 | (3 * 5) + (10 - 6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/9.js: -------------------------------------------------------------------------------- 1 | (3 * 5) + (10 / 2); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/4.js: -------------------------------------------------------------------------------- 1 | const pi = 3.14159; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/5.js: -------------------------------------------------------------------------------- 1 | const radius = 10; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/8.js: -------------------------------------------------------------------------------- 1 | 2 * 4 + (4 - 6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/6.js: -------------------------------------------------------------------------------- 1 | const dx = 0.00001; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/8.js: -------------------------------------------------------------------------------- 1 | list("a", "b", "c"); -------------------------------------------------------------------------------- /docs/lib/empty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * there are no predeclared names here 3 | */ 4 | -------------------------------------------------------------------------------- /sicp_publish/.gitignore: -------------------------------------------------------------------------------- 1 | names.txt 2 | prelude.txt 3 | prelude_names.txt 4 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/11.js: -------------------------------------------------------------------------------- 1 | (((3 / 5) * 2) - 4) + 3; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/2.js: -------------------------------------------------------------------------------- 1 | const size = 2; 2 | size; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection3/1.js: -------------------------------------------------------------------------------- 1 | (2 + 4 * 6) * (3 + 12); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/13.js: -------------------------------------------------------------------------------- 1 | expmod(base, exp / 2, m) -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/2.js: -------------------------------------------------------------------------------- 1 | x => 1.0 / (x * (x + 2)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/9.js: -------------------------------------------------------------------------------- 1 | list(list("george")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/3.js: -------------------------------------------------------------------------------- 1 | const size = 2; 2 | 5 * size; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/12.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | a === b; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/1.js: -------------------------------------------------------------------------------- 1 | pair(list(1, 2), list(3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/1.js: -------------------------------------------------------------------------------- 1 | const a = 1; 2 | const b = 2; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/7.js: -------------------------------------------------------------------------------- 1 | (amount => 25 - amount)(20); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/4.js: -------------------------------------------------------------------------------- 1 | make_withdraw_with_balance -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/section2/4.js: -------------------------------------------------------------------------------- 1 | start(gcd_machine); 2 | "done" -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/10.js: -------------------------------------------------------------------------------- 1 | const a = 3; 2 | const b = a + 1; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/2.js: -------------------------------------------------------------------------------- 1 | const x = pair(1,2); 2 | head(x); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/3.js: -------------------------------------------------------------------------------- 1 | const x = pair(1,2); 2 | tail(x); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/10.js: -------------------------------------------------------------------------------- 1 | const v = list("a", "b", "c"); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/14.js: -------------------------------------------------------------------------------- 1 | list(list("a", "b"), "a", "b") -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/6.js: -------------------------------------------------------------------------------- 1 | const ones = pair(1, () => ones); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection6/6.js: -------------------------------------------------------------------------------- 1 | (+ * a b x y) => (a * x) + (b * y) -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /src/alt-langs/ 2 | /src/py-slang/ 3 | /src/**/__tests__/**/__snapshots__ 4 | -------------------------------------------------------------------------------- /docs/md/EV3_README.md: -------------------------------------------------------------------------------- 1 | The EV3 library lets you control the Lego Mindstorms EV3 robot. 2 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/12.js: -------------------------------------------------------------------------------- 1 | 3 * 2 * (4 + (3 - 5)) + 10 * (27 / 6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/11.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | a + b + a * b; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/1.js: -------------------------------------------------------------------------------- 1 | const x = pair(1,2); 2 | 3 | head(x); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/13.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/17.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/15.js: -------------------------------------------------------------------------------- 1 | save(y); 2 | save(x); 3 | restore(y); -------------------------------------------------------------------------------- /docs/md/README.md: -------------------------------------------------------------------------------- 1 | Changelog: 2 | 3 | styles changed by MH on 1/7/2019, see styles/README.md 4 | -------------------------------------------------------------------------------- /docs/specs/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.aux 3 | *.out 4 | *~ 5 | *.pdf 6 | *.fdb_latexmk 7 | *.fls 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/15.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | 2 + (b > a ? b : a); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/16.js: -------------------------------------------------------------------------------- 1 | function f(g) { 2 | return g(2); 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/6.js: -------------------------------------------------------------------------------- 1 | const plus4 = x => x + 4; 2 | 3 | plus4(3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/3.js: -------------------------------------------------------------------------------- 1 | list("a", "b"); 2 | // ["a", ["b", null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/section2/5.js: -------------------------------------------------------------------------------- 1 | get_register_contents(gcd_machine, "a"); 2 | 2 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection4/3.js: -------------------------------------------------------------------------------- 1 | set_breakpoint(gcd_machine, "test-b", 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection1/13.js: -------------------------------------------------------------------------------- 1 | 3 * 2 * (4 + (3 - 5)) 2 | + 3 | 10 * (27 / 6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/10.js: -------------------------------------------------------------------------------- 1 | tail(list(list("x1", "x2"), list("y1", "y2"))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection1/2.js: -------------------------------------------------------------------------------- 1 | const square = x => x * x; 2 | 3 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/13.js: -------------------------------------------------------------------------------- 1 | const z2 = pair(list("a", "b"), list("a", "b")); -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/images/favicon.ico -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/5.js: -------------------------------------------------------------------------------- 1 | function plus4(x) { return x + 4; } 2 | 3 | plus4(3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/11.js: -------------------------------------------------------------------------------- 1 | tail(head(list(list("x1", "x2"), list("y1", "y2")))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/12.js: -------------------------------------------------------------------------------- 1 | const x = list("a", "b"); 2 | const z1 = pair(x, x); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/section2/2.js: -------------------------------------------------------------------------------- 1 | set_register_contents(gcd_machine, "a", 206); 2 | "done" -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/section2/3.js: -------------------------------------------------------------------------------- 1 | set_register_contents(gcd_machine, "b", 40); 2 | "done" -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection5/2.js: -------------------------------------------------------------------------------- 1 | n === 1 2 | ? 1 3 | : n * factorial(n - 1) -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection5/4.js: -------------------------------------------------------------------------------- 1 | assign("val", constant(1)), 2 | go_to(reg("continue")), -------------------------------------------------------------------------------- /docs/images/sourcepower.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/images/sourcepower.ico -------------------------------------------------------------------------------- /docs/md/GAME_README.md: -------------------------------------------------------------------------------- 1 | The GAME library allows customization of your room in the 2 | Source Academy game. 3 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/8.js: -------------------------------------------------------------------------------- 1 | const circumference = 2 * pi * radius; 2 | circumference; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/13.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | b > a && b < a * b 3 | ? b : a; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/9.js: -------------------------------------------------------------------------------- 1 | const x = list(1, 2, 3); 2 | 3 | const y = list(4, 5, 6); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/example.tmpl: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /docs/language_processing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/language_processing.png -------------------------------------------------------------------------------- /docs/language_processing.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/language_processing.pptx -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection4/2.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | square(21); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/14.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | a === 4 ? 6 : b === 4 ? 6 + 7 + a : 25; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/17.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | a === 4 ? 6 : b === 4 ? 6 + 7 + a : 25; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/13.js: -------------------------------------------------------------------------------- 1 | // returns: [1, [4, [9, [16, [25, [1, [3, [5, [7, null]]]]]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/2.js: -------------------------------------------------------------------------------- 1 | const x = pair(pair(1, pair(2,null)), pair(3, pair(4,null))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection2/3.js: -------------------------------------------------------------------------------- 1 | function make_queue() { 2 | return pair(null, null); 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection3/4.js: -------------------------------------------------------------------------------- 1 | function make_table() { 2 | return list("*table*"); 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection1/17.js: -------------------------------------------------------------------------------- 1 | function show(x) { 2 | display(x); 3 | return x; 4 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section2/subsection1/1.js: -------------------------------------------------------------------------------- 1 | function try_me(a, b) { 2 | return a === 0 ? 1 : b; 3 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "restructuredtext.confPath": "", 3 | "restructuredtext.linter.disabled": true 4 | } 5 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/6.js: -------------------------------------------------------------------------------- 1 | const pi = 3.14159; 2 | const radius = 10; 3 | pi * radius * radius; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | 5 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection4/3.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | square(2 + 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection8/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | 5 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection8/3.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | 5 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection8/4.js: -------------------------------------------------------------------------------- 1 | function square(y) { 2 | return y * y; 3 | } 4 | 5 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/6.js: -------------------------------------------------------------------------------- 1 | function identity(x) { 2 | return x; 3 | } 4 | 5 | identity(42); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/18.js: -------------------------------------------------------------------------------- 1 | function f(g) { 2 | return g(2); 3 | } 4 | f(z => z * (z + 1)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/2.js: -------------------------------------------------------------------------------- 1 | const a = 1; 2 | const b = 2; 3 | list(a, b); 4 | // [1, [2, null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection1/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | 5 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection4/2.js: -------------------------------------------------------------------------------- 1 | function gcd(a, b) { 2 | return b === 0 ? a : gcd(b, a % b); 3 | } -------------------------------------------------------------------------------- /src/tracer/images/tracer-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/src/tracer/images/tracer-1.png -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/README.md: -------------------------------------------------------------------------------- 1 | Changelog: 2 | 3 | styles changed by MH on 1/7/2019, see styles/README.md 4 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection4/4.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | square(square(3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/1.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | 5 | abs(-5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/31.js: -------------------------------------------------------------------------------- 1 | square_list(list(1, 2, 3, 4)); 2 | // returns: [1, [4, [9, [16, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/11.js: -------------------------------------------------------------------------------- 1 | const x = list(1, 2, 3); 2 | 3 | const y = list(4, 5, 6); 4 | pair(x, y); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/12.js: -------------------------------------------------------------------------------- 1 | const x = list(1, 2, 3); 2 | 3 | const y = list(4, 5, 6); 4 | list(x, y); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/20.js: -------------------------------------------------------------------------------- 1 | function make_mobile(left, right) { 2 | return list(left, right); 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/4.js: -------------------------------------------------------------------------------- 1 | const a = 1; 2 | const b = 2; 3 | list("a", b); 4 | // ["a", [2, null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/19.js: -------------------------------------------------------------------------------- 1 | const exp_series = 2 | pair(1, () => integrate_series(exp_series)); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/styles/README.md: -------------------------------------------------------------------------------- 1 | Changelog: 2 | 3 | // jsdoc-default.css modified by MH: 1/7/2019, see MH below -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection5/1.js: -------------------------------------------------------------------------------- 1 | function f(a) { 2 | return sum_of_squares(a + 1, a * 2); 3 | } 4 | f(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/7.js: -------------------------------------------------------------------------------- 1 | function sqrt(x) { 2 | return sqrt_iter(1, x); 3 | } 4 | sqrt(100 + 37); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/9.js: -------------------------------------------------------------------------------- 1 | function sqrt(x) { 2 | return sqrt_iter(1, x); 3 | } 4 | square(sqrt(1000)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection4/4.js: -------------------------------------------------------------------------------- 1 | function is_even(n) { 2 | return n % 2 === 0; 3 | } 4 | 5 | is_even(7); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/17.js: -------------------------------------------------------------------------------- 1 | reverse(list(1, 4, 9, 16, 25)); 2 | // result: [25, [16, [9, [4, [1, null]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/10.js: -------------------------------------------------------------------------------- 1 | const x = list(1, 2, 3); 2 | 3 | const y = list(4, 5, 6); 4 | append(x, y); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/2.js: -------------------------------------------------------------------------------- 1 | const heart2 = beside(heart, flip_vert(heart)); // (a) 2 | 3 | show(heart2); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection2/7.js: -------------------------------------------------------------------------------- 1 | const pi = 3.14159; 2 | const radius = 10; 3 | const circumference = 2 * pi * radius; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/18.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | a === 4 3 | ? 6 4 | : b === 4 5 | ? 6 + 7 + a 6 | : 25; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/3.js: -------------------------------------------------------------------------------- 1 | function average(x,y) { 2 | return (x + y) / 2; 3 | } 4 | 5 | average(3, 6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/8.js: -------------------------------------------------------------------------------- 1 | function sqrt(x) { 2 | return sqrt_iter(1, x); 3 | } 4 | sqrt(sqrt(2) + sqrt(3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/9.js: -------------------------------------------------------------------------------- 1 | const squares = list(1, 4, 9, 16, 25); 2 | list_ref(squares, 3); 3 | // result: 16 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/3.js: -------------------------------------------------------------------------------- 1 | const x = pair(pair(1, pair(2,null)), pair(3, pair(4,null))); 2 | length(x); 3 | // 3 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/20.js: -------------------------------------------------------------------------------- 1 | // make_accumulator to be written by students 2 | const a = make_accumulator(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function make_decrementer(balance) { 2 | return amount => balance - amount; 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/15.js: -------------------------------------------------------------------------------- 1 | function set_to_wow(x) { 2 | set_head(head(x), "wow"); 3 | return x; 4 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/2.js: -------------------------------------------------------------------------------- 1 | function not_equal(x, y) { 2 | return x > y || x < y; 3 | } 4 | 5 | not_equal(7, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/5.js: -------------------------------------------------------------------------------- 1 | const x = pair(1,2); 2 | const y = pair(3,4); 3 | const z = pair(x,y); 4 | head(head(z)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/6.js: -------------------------------------------------------------------------------- 1 | const x = pair(1,2); 2 | const y = pair(3,4); 3 | const z = pair(x,y); 4 | head(tail(z)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/1.js: -------------------------------------------------------------------------------- 1 | pair(1, 2 | pair(2, 3 | pair(3, 4 | pair(4, null)))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/3.js: -------------------------------------------------------------------------------- 1 | const one_through_four = list(1, 2, 3, 4); 2 | head(one_through_four); 3 | // result: 1 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/21.js: -------------------------------------------------------------------------------- 1 | function make_branch(length, structure) { 2 | return list(length, structure); 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function is_variable(x) { 2 | return is_string(x); 3 | } 4 | 5 | is_variable("xyz"); -------------------------------------------------------------------------------- /src/tracer/tracer_supplementary_slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/src/tracer/tracer_supplementary_slides.pdf -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/16.js: -------------------------------------------------------------------------------- 1 | const b = a + 1; 2 | (a > b 3 | ? a 4 | : a < b 5 | ? b 6 | : -1) 7 | * 8 | (a + 1); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/3.js: -------------------------------------------------------------------------------- 1 | function not_equal(x, y) { 2 | return !(x >= y && x <= y); 3 | } 4 | 5 | not_equal(7, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection5/1.js: -------------------------------------------------------------------------------- 1 | function gcd(a, b) { 2 | return b === 0 ? a : gcd(b, a % b); 3 | } 4 | 5 | gcd(20, 12); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/7.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | ((x, y, z) => x + y + square(z))(1, 2, 3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/4.js: -------------------------------------------------------------------------------- 1 | const x = pair(1,2); 2 | const y = pair(3,4); 3 | const z = pair(x,y); 4 | 5 | head(head(z)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection3/3.js: -------------------------------------------------------------------------------- 1 | const zero = f => x => x; 2 | function add_1(n) { 3 | return f => x => f(n(f)(x)); 4 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/21.js: -------------------------------------------------------------------------------- 1 | function plus_curried(x) { 2 | return y => x + y; 3 | } 4 | 5 | plus_curried(3)(4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/5.js: -------------------------------------------------------------------------------- 1 | const one_through_four = list(1, 2, 3, 4); 2 | head(tail(one_through_four)); 3 | // result: 2 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/14.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); 2 | x; 3 | // [[1, [2, null]], [[3, [4, null]], null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/6.js: -------------------------------------------------------------------------------- 1 | const x = pair(pair(1, pair(2,null)), pair(3, pair(4,null))); 2 | length(list(x, x)); 3 | // 2 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/7.js: -------------------------------------------------------------------------------- 1 | function addend(s) { 2 | return head(tail(s)); 3 | } 4 | 5 | addend(make_sum("x", 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/23.js: -------------------------------------------------------------------------------- 1 | // make_monitored function to be written by students 2 | const s = make_monitored(math_sqrt); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection2/7.js: -------------------------------------------------------------------------------- 1 | function make_queue() { 2 | return pair(null, null); 3 | } 4 | const q1 = make_queue(); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/7.js: -------------------------------------------------------------------------------- 1 | function make_label_entry(label_name, insts) { 2 | return pair(label_name, insts); 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/4.js: -------------------------------------------------------------------------------- 1 | function advance_pc(pc) { 2 | set_contents(pc, tail(get_contents(pc))); 3 | 4 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/16.js: -------------------------------------------------------------------------------- 1 | // last_pair to be given by student 2 | last_pair(list(23, 72, 149, 34)); 3 | // result: [34, null] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/18.js: -------------------------------------------------------------------------------- 1 | const us_coins = list(50, 25, 10, 5, 1); 2 | const uk_coins = list(100, 50, 20, 10, 5, 2, 1, 0.5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/36.js: -------------------------------------------------------------------------------- 1 | // for_each to be given by student 2 | for_each(x => display(x), 3 | list(57, 321, 88)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/28.js: -------------------------------------------------------------------------------- 1 | // same as accumulate 2 | const fold_right = accumulate; 3 | fold_right(list, null, list(1, 2, 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/8.js: -------------------------------------------------------------------------------- 1 | function augend(s) { 2 | return head(tail(tail(s))); 3 | } 4 | 5 | augend(make_sum("x", 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/1.js: -------------------------------------------------------------------------------- 1 | const x = list(list("a", "b"), "c"); 2 | const y = list("e", "f"); 3 | const z = pair(y, tail(x)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection4/5.js: -------------------------------------------------------------------------------- 1 | function expt(b, n) { 2 | return n === 0 3 | ? 1 4 | : b * expt(b, n - 1); 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/8.js: -------------------------------------------------------------------------------- 1 | function fib(n) { 2 | return n < 2 3 | ? n 4 | : fib(n - 1) + fib(n - 2); 5 | } -------------------------------------------------------------------------------- /scripts/publish_sicp_package.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | publish() { 4 | cd sicp_publish 5 | npm version patch 6 | npm publish 7 | } 8 | 9 | publish -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/4.js: -------------------------------------------------------------------------------- 1 | const one_through_four = list(1, 2, 3, 4); 2 | tail(one_through_four); 3 | // result: [2, [3, [4, null]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/15.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); 2 | reverse(x); 3 | // [[3, [4, null]], [[1, [2, null]], null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/21.js: -------------------------------------------------------------------------------- 1 | list(list( 1, 2, 3), 2 | list( 4, 5, 6), 3 | list( 7, 8, 9), 4 | list(10, 11, 12)) -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/10.js: -------------------------------------------------------------------------------- 1 | function multiplier(s) { 2 | return head(tail(s)); 3 | } 4 | 5 | multiplier(make_product("x", 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/26.js: -------------------------------------------------------------------------------- 1 | // make_account function to be written by students 2 | const acc = make_account(100, "secret password"); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/15.js: -------------------------------------------------------------------------------- 1 | // mul_streams to be written by students 2 | const factorials = pair(1, () => mul_streams(???, ???)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function remainder(n, d) { 2 | return n < d 3 | ? n 4 | : remainder(n - d, d); 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection6/2.js: -------------------------------------------------------------------------------- 1 | ((x, y) => 2 | ((a, b, c, d, e) => 3 | ((y, z) => x * y * z)(a * b * x, c + d + x)))(3, 4) -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection6/3.js: -------------------------------------------------------------------------------- 1 | find_variable("c", list(list("y", "z"), list("a", "b", "c", "d", "e"), list("x", "y"))); 2 | [1, 2] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection6/4.js: -------------------------------------------------------------------------------- 1 | find_variable("x", list(list("y", "z"), list("a", "b", "c", "d", "e"), list("x", "y"))); 2 | [2, 0] -------------------------------------------------------------------------------- /src/stdlib/object.ts: -------------------------------------------------------------------------------- 1 | import type { Value } from '../types' 2 | 3 | export function is_instance_of(a: Value, b: Value) { 4 | return a instanceof b 5 | } 6 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/20.js: -------------------------------------------------------------------------------- 1 | function p() { 2 | return p(); 3 | } 4 | 5 | function test(x, y) { 6 | return x === 0 ? 0 : y; 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/17.js: -------------------------------------------------------------------------------- 1 | function f(g) { 2 | return g(2); 3 | } 4 | function square(x) { 5 | return x * x; 6 | } 7 | f(square); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/6.js: -------------------------------------------------------------------------------- 1 | function is_sum(x) { 2 | return is_pair(x) && head(x) === "+"; 3 | } 4 | 5 | is_sum(make_sum("x", 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/21.js: -------------------------------------------------------------------------------- 1 | // make_accumulator to be written by students 2 | const a = make_accumulator(5); 3 | a(10); // output: 15 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/24.js: -------------------------------------------------------------------------------- 1 | // make_monitored function to be written by students 2 | const s = make_monitored(math_sqrt); 3 | s(100); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection5/1.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return n === 1 3 | ? 1 4 | : factorial(n - 1) * n; 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection6/5.js: -------------------------------------------------------------------------------- 1 | find_variable("w", list(list("y", "z"), list("a", "b", "c", "d", "e"), list("x", "y"))); 2 | not-found -------------------------------------------------------------------------------- /src/repl/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* istanbul ignore file */ 3 | 4 | import { getMainCommand } from './main' 5 | 6 | getMainCommand().parseAsync() 7 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/2.js: -------------------------------------------------------------------------------- 1 | const one_through_four = list(1, 2, 3, 4); 2 | 3 | one_through_four; 4 | // displays: [1, [2, [3, [4, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/26.js: -------------------------------------------------------------------------------- 1 | // tree_map to be written by student 2 | function square_tree(tree) { 3 | return tree_map(square, tree); 4 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/11.js: -------------------------------------------------------------------------------- 1 | function multiplicand(s) { 2 | return head(tail(tail(s))); 3 | } 4 | 5 | multiplicand(make_product("x", 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/16.js: -------------------------------------------------------------------------------- 1 | function number_equal(exp, num) { 2 | return is_number(exp) && exp === num; 3 | } 4 | 5 | number_equal(3, 3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/18.js: -------------------------------------------------------------------------------- 1 | const z2 = pair(list("a", "b"), list("a", "b")); 2 | z2; 3 | // displays: [["a", ["b", null], ["a", ["b", null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/4.js: -------------------------------------------------------------------------------- 1 | function fibgen(a, b) { 2 | return pair(a, () => fibgen(b, a + b)); 3 | } 4 | 5 | const fibs = fibgen(0, 1); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection7/1.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return n === 1 3 | ? 4 | factorial(n - 1) * n; 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return n === 1 3 | ? 1 4 | : n * factorial(n - 1); 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection5/5.js: -------------------------------------------------------------------------------- 1 | function factorial_alt(n) { 2 | return n === 1 3 | ? 1 4 | : factorial_alt(n - 1) * n; 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/6.js: -------------------------------------------------------------------------------- 1 | const one_through_four = list(1, 2, 3, 4); 2 | pair(10, one_through_four); 3 | // result: [10, [1, [2, [3, [4, null]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/7.js: -------------------------------------------------------------------------------- 1 | const one_through_four = list(1, 2, 3, 4); 2 | pair(5, one_through_four); 3 | // result: [5, [1, [2, [3, [4, null]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/9.js: -------------------------------------------------------------------------------- 1 | function is_product(x) { 2 | return is_pair(x) && head(x) === "*"; 3 | } 4 | 5 | is_product(make_product("x", 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/6.js: -------------------------------------------------------------------------------- 1 | function make_decrementer(balance) { 2 | return amount => balance - amount; 3 | } 4 | (make_decrementer(25))(20); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/16.js: -------------------------------------------------------------------------------- 1 | const x = list("a", "b"); 2 | const z1 = pair(x, x); 3 | z1; 4 | // displays: [["a", ["b", null], ["a", ["b", null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/5.js: -------------------------------------------------------------------------------- 1 | function last_pair(x) { 2 | return is_null(tail(x))) 3 | ? x 4 | : last_pair(tail(x)); 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection6/2.js: -------------------------------------------------------------------------------- 1 | let a = 1; 2 | function f(x) { 3 | let b = a + x; 4 | let a = 5; 5 | return a + b; 6 | } 7 | f(10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection3/11.js: -------------------------------------------------------------------------------- 1 | // cont_frac to be written by student; see exercise 1.37 2 | cont_frac(i => 1.0, 3 | i => 1.0, 4 | k); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/3.js: -------------------------------------------------------------------------------- 1 | function make_decrementer(balance) { 2 | return amount => balance - amount; 3 | } 4 | const d = make_decrementer(25); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection1/4.js: -------------------------------------------------------------------------------- 1 | function stream_tail(stream) { 2 | return tail(stream)(); 3 | } 4 | 5 | stream_tail(pair(4, () => pair(5, () => null))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function is_true(x) { 2 | return x === true; 3 | } 4 | 5 | is_true(1); // should return false because only true is true -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection5/7.js: -------------------------------------------------------------------------------- 1 | assign("val", op("lookup-variable-value"), constant("a"), reg("env")), 2 | assign("val", op("+"), reg("val"), constant(1)), -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "printWidth": 100, 5 | "trailingComma": "none", 6 | "arrowParens": "avoid", 7 | "endOfLine": "auto" 8 | } 9 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/21.js: -------------------------------------------------------------------------------- 1 | function p() { 2 | return p(); 3 | } 4 | 5 | function test(x, y) { 6 | return x === 0 ? 0 : y; 7 | } 8 | test(0, p()); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/10.js: -------------------------------------------------------------------------------- 1 | function conditional(predicate, then_clause, else_clause) { 2 | return predicate ? then_clause : else_clause; 3 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function expt(b,n) { 2 | return n === 0 3 | ? 1 4 | : b * expt(b, n - 1); 5 | } 6 | 7 | expt(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection4/5.js: -------------------------------------------------------------------------------- 1 | function times(a,b) { 2 | return b === 0 3 | ? 0 4 | : a + times(a, b - 1); 5 | } 6 | 7 | times(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/18.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); 2 | // fringe to be written by student 3 | fringe(x); 4 | // [1, [2, [3, [4, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/19.js: -------------------------------------------------------------------------------- 1 | // make_joint function to be written by students 2 | const paul_acc = 3 | make_joint(peter_acc, "open sesame", "rosebud"); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/3.js: -------------------------------------------------------------------------------- 1 | function append(x, y) { 2 | return is_null(x) 3 | ? y 4 | : pair(head(x), append(tail(x), y)); 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/8.js: -------------------------------------------------------------------------------- 1 | function make_cycle(x) { 2 | set_tail(last_pair(x), x); 3 | return x; 4 | } 5 | const z = make_cycle(list("a", "b", "c")); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/README.md: -------------------------------------------------------------------------------- 1 | Changelog, compared to default template 2 | 3 | container.tmpl: 4 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/1.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return n === 1 3 | ? 1 4 | : n * factorial(n - 1); 5 | } 6 | 7 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/30.js: -------------------------------------------------------------------------------- 1 | function scale_list(items, factor) { 2 | return map(x => x * factor, items); 3 | } 4 | 5 | scale_list(list(1, 2, 3, 4, 5), 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/20.js: -------------------------------------------------------------------------------- 1 | function count_leaves(t) { 2 | return accumulate(??, ??, map(??, ??)); 3 | } 4 | 5 | count_leaves(pair(list(1, 2), list(3, 4))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/15.js: -------------------------------------------------------------------------------- 1 | // function split to be written by student 2 | const right_split = split(beside, below); 3 | const up_split = split(below, beside); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/4.js: -------------------------------------------------------------------------------- 1 | function make_sum(a1, a2) { 2 | return list("+", a1, a2); 3 | } 4 | 5 | make_sum(make_product("x", 3), make_product("y", "z")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/22.js: -------------------------------------------------------------------------------- 1 | a(10); // output: 15 2 | // make_accumulator to be written by students 3 | const a = make_accumulator(5); 4 | a(10); // output: 25 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return n === 1 3 | ? 1 4 | : n * factorial(n - 1); 5 | } 6 | 7 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection6/1.js: -------------------------------------------------------------------------------- 1 | function solve(f, y0, dt) { 2 | const y = integral( () => dy, y0, dt); 3 | const dy = stream_map(f, y); 4 | return y; 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection4/1.js: -------------------------------------------------------------------------------- 1 | list(list("initialize-stack", () => stack("initialize")), 2 | list("print-stack-statistics", () => stack("print-statistics"))); -------------------------------------------------------------------------------- /docs/specs/source_parse_tree_types.tex: -------------------------------------------------------------------------------- 1 | \section*{Appendix: Parse Tree Types} 2 | 3 | The types for the result of the parse function are as follows: 4 | 5 | \input ../lib/parsetreetypes.js 6 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/16.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | // repeated to be written by student; see EXERCISE 1.43 5 | repeated(square, 2)(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/33.js: -------------------------------------------------------------------------------- 1 | function flatmap(f, seq) { 2 | return accumulate(append, null, map(f, seq)); 3 | } 4 | 5 | flatmap(x => list(x, x), list(1, 2, 3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/3.js: -------------------------------------------------------------------------------- 1 | const heart2 = beside(heart, flip_vert(heart)); // (a) 2 | const heart4 = stack(heart2, heart2); // (b) 3 | 4 | show(heart4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/14.js: -------------------------------------------------------------------------------- 1 | // function is_equal to be written by student 2 | is_equal(list("this", "is", "a", "list"), 3 | list("this", "is", "a", "list")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection6/1.js: -------------------------------------------------------------------------------- 1 | let x = 3; 2 | let y = 4; 3 | (a, b, c, d, e) => { 4 | let y = a * b * x; 5 | let z = c + d + x; 6 | return x * y * z; 7 | } -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/14.js: -------------------------------------------------------------------------------- 1 | // double to be written by student; see EXERCISE 1.41 2 | function inc(n) { 3 | return n + 1; 4 | } 5 | double(double(double))(inc)(5); // ? -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/5.js: -------------------------------------------------------------------------------- 1 | function deriv(g) { 2 | return x => (g(x + dx) - g(x)) / dx; 3 | } 4 | 5 | function cube(x) { return x * x * x; } 6 | 7 | deriv(cube)(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/33.js: -------------------------------------------------------------------------------- 1 | function square_list(items) { 2 | return map(??, ??); 3 | } 4 | 5 | square_list(list(1, 2, 3, 4)); 6 | // returns: [1, [4, [9, [16, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/15.js: -------------------------------------------------------------------------------- 1 | // function is_equal to be written by student 2 | is_equal(list("this", "is", "a", "list"), 3 | list("this", list("is", "a"), "list")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/25.js: -------------------------------------------------------------------------------- 1 | s(100); 2 | // make_monitored function to be written by students 3 | const s = make_monitored(math_sqrt); 4 | s("how many calls?"); // returns 1 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/28.js: -------------------------------------------------------------------------------- 1 | (acc("secret password", "withdraw"))(40); // result: 60 2 | (acc("some other password", "deposit"))(40); 3 | // result: incorrect password -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/4.js: -------------------------------------------------------------------------------- 1 | const d = make_decrementer(25); 2 | function make_decrementer(balance) { 3 | return amount => balance - amount; 4 | } 5 | d(20); // output: 5 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/14.js: -------------------------------------------------------------------------------- 1 | function add_streams(s1, s2) { 2 | return stream_combine((x1, x2) => x1 + x2, s1, s2); 3 | } 4 | const s = pair(1, () => add_streams(s, s)); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection8/2.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return math_exp(double(math_log(x))); 3 | } 4 | function double(x) { 5 | return x + x; 6 | } 7 | 8 | square(14); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/1.js: -------------------------------------------------------------------------------- 1 | function sum_integers(a, b) { 2 | return a > b 3 | ? 0 4 | : a + sum_integers(a + 1, b); 5 | } 6 | 7 | sum_integers(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/22.js: -------------------------------------------------------------------------------- 1 | function plus_curried(x) { 2 | return y => x + y; 3 | } 4 | // brooks to be written by the student 5 | brooks(plus_curried, list(3, 4)); -------------------------------------------------------------------------------- /docs/jsdoc/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates": { 3 | "cleverLinks": false, 4 | "monospaceLinks": false, 5 | "default": { 6 | "outputSourceFiles": false 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/11.js: -------------------------------------------------------------------------------- 1 | function h() { 2 | const x = 1; 3 | function i() { 4 | const x = x + 1; 5 | return x; 6 | } 7 | return i(); 8 | } 9 | h(); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/15.js: -------------------------------------------------------------------------------- 1 | function append(list1, list2) { 2 | return is_null(list1) 3 | ? list2 4 | : pair(head(list1), append(tail(list1), list2)); 5 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/16.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); 2 | // deep_reverse to be written by student 3 | deep_reverse(x); 4 | // [[4, [3, null]], [[2, [1, null]], null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/19.js: -------------------------------------------------------------------------------- 1 | const x = list(list(1, 2), list(3, 4)); 2 | // fringe to be written by student 3 | fringe(list(x, x)); 4 | // [1, [2, [3, [4, [1, [2, [3, [4, null]]]]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/26.js: -------------------------------------------------------------------------------- 1 | // same as accumulate 2 | const fold_right = accumulate; 3 | function divide(x, y) { 4 | return x / y; 5 | } 6 | fold_right(divide, 1, list(1, 2, 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection3/9.js: -------------------------------------------------------------------------------- 1 | function fib(n) { 2 | return n === 0 3 | ? 0 4 | : n === 1 5 | ? 1 6 | : fib(n - 1) + fib(n - 2); 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/18.js: -------------------------------------------------------------------------------- 1 | function expand(num, den, radix) { 2 | return pair(quotient(num * radix, den), 3 | expand((num * radix) % den, den, radix)); 4 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection2/3.js: -------------------------------------------------------------------------------- 1 | function is_tagged_list(stmt, the_tag) { 2 | return is_pair(stmt) && head(stmt) === the_tag; 3 | } 4 | 5 | is_tagged_list(list("name", "x"), "name"); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section4/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function sum_of_squares(x, y) { 5 | return square(x) + square(y); 6 | } 7 | sum_of_squares(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection4/3.js: -------------------------------------------------------------------------------- 1 | function fib(n) { 2 | return n === 0 3 | ? 0 4 | : n === 1 5 | ? 1 6 | : fib(n - 1) + fib(n - 2); 7 | } -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/static/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/js-slang/HEAD/docs/jsdoc/templates/template/static/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /docs/specs/source_list_library.tex: -------------------------------------------------------------------------------- 1 | \section*{Appendix: List library} 2 | 3 | Those list library functions that are not primitive functions are pre-declared as follows: 4 | 5 | \input ../lib/list.js 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/specs/source_stream_library.tex: -------------------------------------------------------------------------------- 1 | \section*{Appendix: Stream library} 2 | 3 | Those stream library functions that are not primitive functions are pre-declared as follows: 4 | 5 | \input ../lib/stream.js 6 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection4/5.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function sum_of_squares(x,y) { 5 | return square(x) + square(y); 6 | } 7 | 8 | sum_of_squares(3,4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/11.js: -------------------------------------------------------------------------------- 1 | function conditional(predicate, then_clause, else_clause) { 2 | return predicate ? then_clause : else_clause; 3 | } 4 | conditional(2 === 3, 0, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/12.js: -------------------------------------------------------------------------------- 1 | function conditional(predicate, then_clause, else_clause) { 2 | return predicate ? then_clause : else_clause; 3 | } 4 | conditional(1 === 1, 0, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function pair(x, y) { 2 | return m => m(x, y); 3 | } 4 | function head(z) { 5 | return z((p, q) => p); 6 | } 7 | 8 | const x = pair(1,2); 9 | head(x); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/38.js: -------------------------------------------------------------------------------- 1 | function remove(item, sequence) { 2 | return filter(x => !(x === item), 3 | sequence); 4 | } 5 | 6 | remove(3, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection6/3.js: -------------------------------------------------------------------------------- 1 | (n => (fact => fact(fact, n)) 2 | ( (ft, k) => k === 1 3 | ? 1 4 | : k * ft(ft, k - 1) 5 | ) 6 | ) 7 | (10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/2.js: -------------------------------------------------------------------------------- 1 | function average(x,y) { 2 | return (x + y) / 2; 3 | } 4 | function improve(guess, x) { 5 | return average(guess, x / guess); 6 | } 7 | 8 | improve(3, 25); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/7.js: -------------------------------------------------------------------------------- 1 | const dx = 0.00001; 2 | function deriv(g) { 3 | return x => (g(x + dx) - g(x)) / dx; 4 | } 5 | function cube(x) { return x * x * x; } 6 | 7 | deriv(cube)(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/23.js: -------------------------------------------------------------------------------- 1 | function plus_curried(x) { 2 | return y => x + y; 3 | } 4 | // brooks_curried to be written by the student 5 | brooks_curried(list(plus_curried, 3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/27.js: -------------------------------------------------------------------------------- 1 | // make_account function to be written by students 2 | const acc = make_account(100, "secret password"); 3 | (acc("secret password", "withdraw"))(40); // result: 60 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/10.js: -------------------------------------------------------------------------------- 1 | function make_decrementer(balance) { 2 | return amount => balance - amount; 3 | } 4 | const d1 = make_decrementer(25); 5 | 6 | const d2 = make_decrementer(25); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/20.js: -------------------------------------------------------------------------------- 1 | function count_pairs(x) { 2 | return !is_pair(x) 3 | ? 0 4 | : count_pairs(head(x)) + 5 | count_pairs(tail(x)) + 1; 6 | } -------------------------------------------------------------------------------- /docs/specs/source_python_comments.tex: -------------------------------------------------------------------------------- 1 | \subsection*{\href{https://sourceacademy.org/sicpjs/2.2.3\#footnote-8}{Comments}} 2 | 3 | In Python \S 1, any characters after ``\#'' until the next newline character is ignored. 4 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | function close_enough(x,y) { 5 | return abs(x - y) < 0.001; 6 | } 7 | 8 | close_enough(7.7654, 7.7666); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function average(x,y) { 2 | return (x + y) / 2; 3 | } 4 | function average_damp(f) { 5 | return x => average(x, f(x)); 6 | } 7 | 8 | average_damp(square)(10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/7.js: -------------------------------------------------------------------------------- 1 | function make_rat(n, d) { 2 | return pair(n, d); 3 | } 4 | function numer(x) { 5 | return head(x); 6 | } 7 | function denom(x) { 8 | return tail(x); 9 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/22.js: -------------------------------------------------------------------------------- 1 | function make_mobile(left, right) { 2 | return pair(left, right); 3 | } 4 | function make_branch(length, structure) { 5 | return pair(length, structure); 6 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/5.js: -------------------------------------------------------------------------------- 1 | const x = pair(pair(1, pair(2,null)), pair(3, pair(4,null))); 2 | list(x, x); 3 | // [[[[1, [2, null]], [3, [4, null]]], 4 | // [[[1, [2, null]], [3, [4, null]]], null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/5.js: -------------------------------------------------------------------------------- 1 | d(20); // output: 5 2 | const d = make_decrementer(25); 3 | function make_decrementer(balance) { 4 | return amount => balance - amount; 5 | } 6 | d(10); // output: 15 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/3.js: -------------------------------------------------------------------------------- 1 | function start_eceval() { 2 | the_global_environment = setup_environment(); 3 | set_register_contents(eceval, "flag", false); 4 | return start(eceval); 5 | } -------------------------------------------------------------------------------- /src/runner/types.ts: -------------------------------------------------------------------------------- 1 | import type { Program } from 'estree' 2 | import type { Context, IOptions, Result } from '..' 3 | 4 | export type Runner = (program: Program, context: Context, options: IOptions) => Promise 5 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function fib(n) { 2 | return n === 0 3 | ? 0 4 | : n === 1 5 | ? 1 6 | : fib(n - 1) + fib(n - 2); 7 | } 8 | 9 | fib(6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/3.js: -------------------------------------------------------------------------------- 1 | function pi_sum(a, b) { 2 | return a > b 3 | ? 0 4 | : 1.0 / (a * (a + 2)) + 5 | pi_sum(a + 4, b); 6 | } 7 | 8 | 8 * pi_sum(1, 1000); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/30.js: -------------------------------------------------------------------------------- 1 | function reverse(sequence) { 2 | return fold_right((x, y) => ??, null, sequence); 3 | } 4 | 5 | reverse(list(1, 4, 9, 16, 25)); 6 | // result: [25, [16, [9, [4, [1, null]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/31.js: -------------------------------------------------------------------------------- 1 | function reverse(sequence) { 2 | return fold_left((x, y) => ??, null, sequence); 3 | } 4 | 5 | reverse(list(1, 4, 9, 16, 25)); 6 | // result: [25, [16, [9, [4, [1, null]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/35.js: -------------------------------------------------------------------------------- 1 | function make_pair_sum(pair) { 2 | return list(head(pair), head(tail(pair)), 3 | head(pair) + head(tail(pair))); 4 | } 5 | 6 | make_pair_sum(list(8, 9)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/5.js: -------------------------------------------------------------------------------- 1 | function flipped_pairs(painter) { 2 | const painter2 = beside(painter, flip_vert(painter)); 3 | return stack(painter2, painter2); 4 | } 5 | const heart4 = flipped_pairs(heart); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/11.js: -------------------------------------------------------------------------------- 1 | function scale_stream(stream, factor) { 2 | return stream_map(x => x * factor, 3 | stream); 4 | } 5 | const double = pair(1, () => scale_stream(double, 2)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/15.js: -------------------------------------------------------------------------------- 1 | // compose to be written by student; see EXERCISE 1.42 2 | function square(x) { 3 | return x * x; 4 | } 5 | function inc(n) { 6 | return n + 1; 7 | } 8 | compose(square, inc)(6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/4.js: -------------------------------------------------------------------------------- 1 | function flipped_pairs(painter) { 2 | const painter2 = beside(painter, flip_vert(painter)); 3 | return stack(painter2, painter2); 4 | } 5 | 6 | const heart4 = flipped_pairs(heart); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/5.js: -------------------------------------------------------------------------------- 1 | "external_entry", 2 | perform(op("initialize_stack")), 3 | assign("env", op("get_global_environment")), 4 | assign("continue", label("print_result")), 5 | go_to(reg("val")), -------------------------------------------------------------------------------- /src/typings/acorn-loose.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'acorn-loose' { 2 | import { Options as AcornOptions } from 'acorn' 3 | import * as es from 'estree' 4 | 5 | export function parse(source: string, options: AcornOptions): es.Program 6 | } 7 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/14.js: -------------------------------------------------------------------------------- 1 | function gcd(a, b) { 2 | return b === 0 ? a : gcd(b, a % b); 3 | } 4 | function make_rat(n, d) { 5 | const g = gcd(n, d); 6 | return pair(n / g, d / g); 7 | } 8 | 9 | make_rat(4,6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection4/2.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | function square(x) { 5 | return x * x; 6 | } 7 | function good_enough(guess) { 8 | return abs(square(guess) - x) < 0.001; 9 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/4.js: -------------------------------------------------------------------------------- 1 | function last_pair(x) { 2 | return is_null(tail(x))) 3 | ? x 4 | : last_pair(tail(x)); 5 | } 6 | function append_mutator(x, y) { 7 | set_tail(last_pair(x), y); 8 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/alt-langs/scheme/scm-slang"] 2 | path = src/alt-langs/scheme/scm-slang 3 | url = ../../source-academy/scm-slang.git 4 | [submodule "src/py-slang"] 5 | path = src/py-slang 6 | url = ../../source-academy/py-slang.git 7 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection6/19.js: -------------------------------------------------------------------------------- 1 | function plus(a, b) { return a + b; } 2 | function minus(a, b) { return a - b; } 3 | function a_plus_abs_b(a, b) { 4 | return (b >= 0 ? plus : minus)(a, b); 5 | } 6 | 7 | a_plus_abs_b(5, -4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/10.js: -------------------------------------------------------------------------------- 1 | function length(items) { 2 | return is_null(items) 3 | ? 0 4 | : 1 + length(tail(items)); 5 | } 6 | 7 | const odds = list(1, 3, 5, 7); 8 | length(odds); 9 | // returns: 4 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function integers_starting_from(n) { 2 | return pair(n, 3 | () => integers_starting_from(n + 1) 4 | ); 5 | } 6 | 7 | eval_stream(integers_starting_from(7), 30); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/source.tmpl: -------------------------------------------------------------------------------- 1 | 4 |
5 |
6 |
7 |
8 |
-------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/32.js: -------------------------------------------------------------------------------- 1 | function square_list(items) { 2 | return is_null(items) 3 | ? null 4 | : pair(??, ??); 5 | } 6 | 7 | square_list(list(1, 2, 3, 4)); 8 | // returns: [1, [4, [9, [16, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/5.js: -------------------------------------------------------------------------------- 1 | function inc(x) { 2 | return x + 1; 3 | } 4 | function dec(x) { 5 | return x - 1; 6 | } 7 | function plus(a, b) { 8 | return a === 0 ? b : plus(dec(a), inc(b)); 9 | } 10 | 11 | plus(4, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/24.js: -------------------------------------------------------------------------------- 1 | function plus_curried(x) { 2 | return y => x + y; 3 | } 4 | // brooks_curried to be written by the student 5 | brooks_curried(list(brooks_curried, 6 | list(plus_curried, 3, 4))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/6.js: -------------------------------------------------------------------------------- 1 | function accumulate(op, initial, sequence) { 2 | return is_null(sequence) 3 | ? initial 4 | : op(head(sequence), 5 | accumulate(op, initial, tail(sequence))); 6 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/5.js: -------------------------------------------------------------------------------- 1 | function make_sum(a1, a2) { 2 | return list("+", a1, a2); 3 | } 4 | function make_product(m1, m2) { 5 | return list("*", m1, m2); 6 | } 7 | 8 | make_sum(make_product("x", 3), make_product("y", "z")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/7.js: -------------------------------------------------------------------------------- 1 | function last_pair(x) { 2 | return is_null(tail(x))) 3 | ? x 4 | : last_pair(tail(x)); 5 | } 6 | function make_cycle(x) { 7 | set_tail(last_pair(x), x); 8 | return x; 9 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/3.js: -------------------------------------------------------------------------------- 1 | function assign_reg_name(assign_instruction) { 2 | return head(tail(assign_instruction)); 3 | } 4 | 5 | function assign_value_exp(assign_instruction) { 6 | return tail(tail(assign_instruction)); 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section4/subsection4/1.js: -------------------------------------------------------------------------------- 1 | "print_result", 2 | perform(op("print_stack_statistics")), // added instruction 3 | perform(op("announce_output"), const("/// EC-Eval value:")), 4 | /* ... same as before ... */ -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | time: "07:00" 8 | open-pull-requests-limit: 0 # disabled for `renovate` migration (might switch back in the future) 9 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/4.js: -------------------------------------------------------------------------------- 1 | function inc(x) { 2 | return x + 1; 3 | } 4 | function dec(x) { 5 | return x - 1; 6 | } 7 | function plus(a, b) { 8 | return a === 0 ? b : inc(plus(dec(a), b)); 9 | } 10 | 11 | plus(4, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/2.js: -------------------------------------------------------------------------------- 1 | function cube(x) { 2 | return x * x * x; 3 | } 4 | function sum_cubes(a, b) { 5 | return a > b 6 | ? 0 7 | : cube(a) + sum_cubes(a + 1, b); 8 | } 9 | 10 | sum_cubes(3, 7); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/29.js: -------------------------------------------------------------------------------- 1 | function map(fun, items) { 2 | return is_null(items) 3 | ? null 4 | : pair(fun(head(items)), 5 | map(fun, tail(items))); 6 | } 7 | map(x => x * x, list(1, 2, 3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/10.js: -------------------------------------------------------------------------------- 1 | function enumerate_interval(low, high) { 2 | return low > high 3 | ? null 4 | : pair(low, 5 | enumerate_interval(low + 1, high)); 6 | } 7 | 8 | enumerate_interval(2, 7); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/19.js: -------------------------------------------------------------------------------- 1 | function set_to_wow(x) { 2 | set_head(head(x), "wow"); 3 | return x; 4 | } 5 | const z2 = pair(list("a", "b"), list("a", "b")); 6 | set_to_wow(z2); 7 | // displays: [["wow", ["b", null], ["a", ["b", null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/27.js: -------------------------------------------------------------------------------- 1 | function map(fun, items) { 2 | return is_null(items) 3 | ? null 4 | : pair(fun(head(items)), 5 | map(fun, tail(items))); 6 | } 7 | 8 | map(abs, list(-10, 2.5, -11.6, 17)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/6.js: -------------------------------------------------------------------------------- 1 | function member(item, x) { 2 | return is_null(x) 3 | ? false 4 | : item === head(x) 5 | ? x 6 | : member(item, tail(x)); 7 | } 8 | member("apple", list("pear", "banana", "prune")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/9.js: -------------------------------------------------------------------------------- 1 | function make_simplified_withdraw(balance) { 2 | return amount => { 3 | balance = balance - amount; 4 | return balance; 5 | }; 6 | } 7 | (make_simplified_withdraw(25))(20); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/8.js: -------------------------------------------------------------------------------- 1 | function lookup_label(labels, label_name) { 2 | const val = assoc(label_name, labels); 3 | 4 | return val === undefined 5 | ? error(label_name, "Undefined label: ASSEMBLE") 6 | : tail(val); 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/9.js: -------------------------------------------------------------------------------- 1 | "start" 2 | go_to(label(here)), 3 | "here", 4 | assign("a", list(const(3))), 5 | go_to(label(there)), 6 | "here", 7 | assign("a", list(const(4))), 8 | go_to(label(there)), 9 | "there", -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection4/6.js: -------------------------------------------------------------------------------- 1 | function sum_of_squares(x,y) { 2 | return square(x) + square(y); 3 | } 4 | function square(x) { 5 | return x * x; 6 | } 7 | function f(a) { 8 | return sum_of_squares(a + 1, a * 2); 9 | } 10 | 11 | f(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function fib(n) { 2 | return fib_iter(1, 0, n); 3 | } 4 | function fib_iter(a, b, count) { 5 | return count === 0 6 | ? b 7 | : fib_iter(a + b, a, count - 1); 8 | } 9 | 10 | fib(6); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection4/2.js: -------------------------------------------------------------------------------- 1 | function average_damp(f) { 2 | return x => average(x, f(x)); 3 | } 4 | function average(x,y) { 5 | return (x + y) / 2; 6 | } 7 | function square(x) { 8 | return x * x; 9 | } 10 | average_damp(square)(10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/13.js: -------------------------------------------------------------------------------- 1 | function member(item, x) { 2 | return is_null(x) 3 | ? false 4 | : item === head(x) 5 | ? x 6 | : member(item, tail(x)); 7 | } 8 | member("red", list("red", "shoes", "blue", "socks")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/5.js: -------------------------------------------------------------------------------- 1 | function member(item, x) { 2 | return is_null(x) 3 | ? false 4 | : item === head(x) 5 | ? x 6 | : member(item, tail(x)); 7 | } 8 | 9 | member("apple", list("pear", "banana", "prune")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/17.js: -------------------------------------------------------------------------------- 1 | function set_to_wow(x) { 2 | set_head(head(x), "wow"); 3 | return x; 4 | } 5 | const x = list("a", "b"); 6 | const z1 = pair(x, x); 7 | set_to_wow(z1); 8 | // displays: [["wow", ["b", null], ["wow", ["b", null]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection3/5.js: -------------------------------------------------------------------------------- 1 | function make_frame(names, values) { 2 | return pair(names, values); 3 | } 4 | function frame_names(frame) { 5 | return head(frame); 6 | } 7 | function frame_values(frame) { 8 | return tail(frame); 9 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/14.js: -------------------------------------------------------------------------------- 1 | function lookup_prim(symbol, operations) { 2 | const val = assoc(symbol, operations); 3 | 4 | return val === undefined 5 | ? error(symbol, "Unknown operation: ASSEMBLE") 6 | : head(tail(val)); 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/8.js: -------------------------------------------------------------------------------- 1 | function list_ref(items, n) { 2 | return n === 0 3 | ? head(items) 4 | : list_ref(tail(items), n - 1); 5 | } 6 | 7 | const squares = list(1, 4, 9, 16, 25); 8 | list_ref(squares, 3); 9 | // result: 16 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/3.js: -------------------------------------------------------------------------------- 1 | function is_variable(x) { 2 | return is_string(x); 3 | } 4 | function is_same_variable(v1, v2) { 5 | return is_variable(v1) && 6 | is_variable(v2) && v1 === v2; 7 | } 8 | 9 | is_same_variable("xyz", "xyz"); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection5/6.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | function iter(product, counter) { 3 | return counter > n 4 | ? product 5 | : iter(product * counter, counter + 1); 6 | } 7 | 8 | return iter(1, 1); 9 | } -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/type.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | | 7 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/7.js: -------------------------------------------------------------------------------- 1 | function A(x,y) { 2 | return y === 0 3 | ? 0 4 | : x === 0 5 | ? 2 * y 6 | : y === 1 7 | ? 2 8 | : A(x - 1, A(x, y - 1)); 9 | } 10 | A(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/8.js: -------------------------------------------------------------------------------- 1 | function A(x,y) { 2 | return y === 0 3 | ? 0 4 | : x === 0 5 | ? 2 * y 6 | : y === 1 7 | ? 2 8 | : A(x - 1, A(x, y - 1)); 9 | } 10 | A(2, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/9.js: -------------------------------------------------------------------------------- 1 | function A(x,y) { 2 | return y === 0 3 | ? 0 4 | : x === 0 5 | ? 2 * y 6 | : y === 1 7 | ? 2 8 | : A(x - 1, A(x, y - 1)); 9 | } 10 | A(3, 3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection4/6.js: -------------------------------------------------------------------------------- 1 | function expt(b, n) { 2 | function expt_iter(counter, product) { 3 | return counter === 0 4 | ? product 5 | : expt_iter(counter - 1, b * product); 6 | } 7 | return expt_iter(n, 1); 8 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/4.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | function square(x) { 5 | return x * x; 6 | } 7 | function good_enough(guess, x) { 8 | return abs(square(guess) - x) < 0.001; 9 | } 10 | 11 | good_enough(1.41, 2); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection8/5.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | function square(x) { 5 | return x * x; 6 | } 7 | function good_enough(guess, x) { 8 | return abs(square(guess) - x) < 0.001; 9 | } 10 | 11 | good_enough(1.41, 2); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/6.js: -------------------------------------------------------------------------------- 1 | function A(x,y) { 2 | return y === 0 3 | ? 0 4 | : x === 0 5 | ? 2 * y 6 | : y === 1 7 | ? 2 8 | : A(x - 1, A(x, y - 1)); 9 | } 10 | 11 | A(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/10.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function f(x, y) { 5 | const a = 1 + x * y; 6 | const b = 1 - y; 7 | return x * square(a) + 8 | y * b + 9 | a * b; 10 | } 11 | 12 | f(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/19.js: -------------------------------------------------------------------------------- 1 | function horner_eval(x, coefficient_sequence) { 2 | return accumulate((this_coeff, higher_terms) => ??, 3 | 0, 4 | coefficient_sequence); 5 | } 6 | horner_eval(2, list(1, 3, 0, 5, 0, 1)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/12.js: -------------------------------------------------------------------------------- 1 | function member(item, x) { 2 | return is_null(x) 3 | ? false 4 | : item === head(x) 5 | ? x 6 | : member(item, tail(x)); 7 | } 8 | member("red", list(list("red", "shoes"), list("blue", "socks"))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | 5 | function sum_of_squares(x, y) { 6 | return square(x) + square(y); 7 | } 8 | 9 | function f(a) { 10 | return sum_of_squares(a + 1, a * 2); 11 | } 12 | 13 | f(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/26.js: -------------------------------------------------------------------------------- 1 | function scale_list(items, factor) { 2 | return is_null(items) 3 | ? null 4 | : pair(head(items) * factor, 5 | scale_list(tail(items), factor)); 6 | } 7 | 8 | scale_list(list(1, 2, 3, 4, 5), 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/18.js: -------------------------------------------------------------------------------- 1 | function horner_eval(x, coefficient_sequence) { 2 | return accumulate((this_coeff, higher_terms) => ??, 3 | 0, 4 | coefficient_sequence); 5 | } 6 | 7 | horner_eval(2, list(1, 3, 0, 5, 0, 1)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function assemble(controller_text, machine) { 2 | function receive(insts, labels) { 3 | update_insts(insts, labels, machine); 4 | return insts; 5 | } 6 | 7 | return extract_labels(controller_text, receive); 8 | } -------------------------------------------------------------------------------- /docs/md/README_AUXILIARY.md: -------------------------------------------------------------------------------- 1 | On the right, you see all predeclared names of AUXILIARY, in alphabetical order. 2 | Click on a name to see how it is defined and used. 3 | 4 | Unlike MISC, the names declared in AUXILIARY are not meant to be directly called, although they can be. 5 | -------------------------------------------------------------------------------- /docs/specs/source_export.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Export directives} 2 | 3 | Export directives allow programs to export values from modules and bind them to names, so that they can be imported by other modules. Export directives can only appear at the top-level, and hence can only export top-level variables. 4 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/9.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function f(x,y) { 5 | return ( (a,b) => x * square(a) + 6 | y * b + 7 | a * b 8 | )(1 + x * y, 1 - y); 9 | } 10 | 11 | f(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection1/7.js: -------------------------------------------------------------------------------- 1 | function member(item, x) { 2 | return is_null(x) 3 | ? false 4 | : item === head(x) 5 | ? x 6 | : member(item, tail(x)); 7 | } 8 | member("apple", 9 | list("x", list("apple","sauce"), "y", "apple", "pear")); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function integral(integrand, intial_value, dt) { 2 | return pair(intial_value, 3 | is_null(integrand) ? null 4 | : integral(stream_tail(integrand), 5 | dt * head(integrand) + initial_value, 6 | dt)); 7 | } -------------------------------------------------------------------------------- /docs/lib/continuation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Generate a continuation cont, 3 | * and call f(cont). 4 | * @param {function} f - A function of the form (cont) => ... 5 | * @returns the return value of f if cont is not consumed 6 | */ 7 | function call_cc(f) {} 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/25.js: -------------------------------------------------------------------------------- 1 | function plus_curried(x) { 2 | return y => x + y; 3 | } 4 | // brooks_curried to be written by the student 5 | brooks_curried(list(brooks_curried, 6 | list(brooks_curried, 7 | list(plus_curried, 3, 4)))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/9.js: -------------------------------------------------------------------------------- 1 | function accumulate(op, initial, sequence) { 2 | return is_null(sequence) 3 | ? initial 4 | : op(head(sequence), 5 | accumulate(op, initial, tail(sequence))); 6 | } 7 | accumulate(pair, null, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection5/1.js: -------------------------------------------------------------------------------- 1 | compile(parse(" \ 2 | function factorial(n) { \ 3 | return n === 1 \ 4 | ? 1" \ 5 | : n * factorial(n - 1);\ 6 | } "), 7 | "val", 8 | "next"); -------------------------------------------------------------------------------- /docs/specs/source_comments.tex: -------------------------------------------------------------------------------- 1 | \subsection*{\href{https://sourceacademy.org/sicpjs/2.2.3\#footnote-8}{Comments}} 2 | 3 | In Source, any sequence of characters between ``\texttt{/*}'' and 4 | the next ``\texttt{*/}'' is ignored. 5 | 6 | After ``//'' any characters until the next newline character is ignored. 7 | -------------------------------------------------------------------------------- /docs/specs/source_studio_2_return.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Restrictions} 2 | 3 | \begin{itemize} 4 | \item There cannot be any newline character between 5 | $\textbf{\texttt{return}}$ and $\textit{expression}$ in return statements.\footnote{ 6 | Source inherits this syntactic quirk of JavaScript.} 7 | \end{itemize} 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection4/8.js: -------------------------------------------------------------------------------- 1 | // encode_symbol function to be written by students 2 | function encode(message, tree) { 3 | return is_null(message) 4 | ? null 5 | : append(encode_symbol(head(message), tree), 6 | encode(tail(message), tree)); 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/1.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | withdraw(25); // output: 75 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section4/section4/1.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | withdraw(25); // output: 75 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/8.js: -------------------------------------------------------------------------------- 1 | function right_split(painter, n) { 2 | if (n === 0) { 3 | return painter; 4 | } else { 5 | const smaller = right_split(painter, n - 1); 6 | return beside(painter, stack(smaller, smaller)); 7 | } 8 | } 9 | show(right_split(heart, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/5.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | 12 | withdraw(25); // output: 75 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection4/5.js: -------------------------------------------------------------------------------- 1 | function apply_primitive_function(fun, argument_list) { 2 | return apply_in_underlying_javascript( 3 | primitive_implementation(fun), 4 | argument_list); 5 | } 6 | 7 | apply_primitive_function(my_primitive_plus, list(1, 2)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/4.js: -------------------------------------------------------------------------------- 1 | function assemble_alternative(controller_text, machine) { 2 | const result = extract_labels(controller_text); 3 | const insts = head(result); 4 | const labels = tail(result); 5 | 6 | update_insts(insts, labels, machine); 7 | 8 | return insts; 9 | } -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/augments.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/modifies.tmpl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 |
7 |
8 | Type 9 |
10 |
11 | 12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/25.js: -------------------------------------------------------------------------------- 1 | // square_tree to be written by student 2 | square_tree(list(1, 3 | list(2, list(3, 4), 5), 4 | list(6, 7))); 5 | // result: [1, [[4, [[9, [16, null]], 6 | // [25, null]]], 7 | // [[36, [49, null]], null]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/3.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function map(fun, items) { 5 | return is_null(items) 6 | ? null 7 | : pair(fun(head(items)), 8 | map(fun, tail(items))); 9 | } 10 | map(square, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/11.js: -------------------------------------------------------------------------------- 1 | function make_simplified_withdraw(balance) { 2 | return amount => { 3 | balance = balance - amount; 4 | return balance; 5 | }; 6 | } 7 | const w1 = make_simplified_withdraw(25); 8 | 9 | const w2 = make_simplified_withdraw(25); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section4/subsection1/1.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | function withdraw(amount) { 3 | if (balance >= amount) { 4 | balance = balance - amount; 5 | return balance; 6 | } else { 7 | return "Insufficient funds"; 8 | } 9 | } 10 | 11 | withdraw(25); // output: 75 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/8.js: -------------------------------------------------------------------------------- 1 | function count_leaves(x) { 2 | return is_null(x) 3 | ? 0 4 | : ! is_pair(x) 5 | ? 1 6 | : count_leaves(head(x)) + 7 | count_leaves(tail(x)); 8 | } 9 | 10 | count_leaves(pair(list(1, 2), list(3, 4))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/24.js: -------------------------------------------------------------------------------- 1 | function matrix_times_vector(m, v) { 2 | return map(??, m); 3 | } 4 | 5 | function transpose(mat) { 6 | return accumulate_n(??, ??, mat); 7 | } 8 | 9 | function matrix_times_matrix(n, m) { 10 | const cols = transpose(n); 11 | return map(??, m); 12 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/28.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | function map(fun, items) { 5 | return is_null(items) 6 | ? null 7 | : pair(fun(head(items)), 8 | map(fun, tail(items))); 9 | } 10 | map(abs, list(-10, 2.5, -11.6, 17)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/6.js: -------------------------------------------------------------------------------- 1 | function right_split(painter, n) { 2 | if (n === 0) { 3 | return painter; 4 | } else { 5 | const smaller = right_split(painter, n - 1); 6 | return beside(painter, stack(smaller, smaller)); 7 | } 8 | } 9 | 10 | show(right_split(heart, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/2.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | function iter(product, counter) { 3 | return counter > n 4 | ? product 5 | : iter(counter * product, 6 | counter + 1); 7 | } 8 | return iter(1, 1); 9 | } 10 | 11 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/7.js: -------------------------------------------------------------------------------- 1 | function make_withdraw_with_balance(balance) { 2 | return amount => { 3 | if (balance >= amount) { 4 | balance = balance - amount; 5 | return balance; 6 | } else { 7 | return "insufficient funds"; 8 | } 9 | }; 10 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/12.js: -------------------------------------------------------------------------------- 1 | const w1 = make_simplified_withdraw(25); 2 | 3 | const w2 = make_simplified_withdraw(25); 4 | function make_simplified_withdraw(balance) { 5 | return amount => { 6 | balance = balance - amount; 7 | return balance; 8 | }; 9 | } 10 | w1(20); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function make_withdraw_with_balance(balance) { 2 | return amount => { 3 | if (balance >= amount) { 4 | balance = balance - amount; 5 | return balance; 6 | } else { 7 | return "insufficient funds"; 8 | } 9 | }; 10 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function front_ptr(queue) { 2 | return head(queue); 3 | } 4 | function rear_ptr(queue) { 5 | return tail(queue); 6 | } 7 | function set_front_ptr(queue, item) { 8 | set_head(queue, item); 9 | } 10 | function set_rear_ptr(queue, item) { 11 | set_tail(queue, item); 12 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section4/section4/2.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | withdraw(25); // output: 75 12 | withdraw(25); // output: 50 -------------------------------------------------------------------------------- /docs/specs/source_python_integers.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Integers} 2 | 3 | We represent integers as whole numbers without any decimal component. Integers can be positive, negative or zero. Integers have arbitrary-precision, meaning they can represent extremely large values without loss of precision. Integers are automatically converted to floats as needed. -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/2.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | withdraw(25); // output: 75 12 | withdraw(25); // output: 50 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function make_simplified_withdraw(balance) { 2 | return amount => { 3 | balance = balance - amount; 4 | return balance; 5 | }; 6 | } 7 | 8 | const w = make_simplified_withdraw(25); 9 | 10 | w(20); // output: 5 11 | 12 | w(10); // output: -5 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection1/11.js: -------------------------------------------------------------------------------- 1 | function eval_assignment(stmt, env) { 2 | const value = evaluate(assignment_value(stmt), env); 3 | assign_name_value(assignment_name(stmt), value, env); 4 | return value; 5 | } 6 | 7 | const my_program = parse("{ let x = 1; x = 2; }"); 8 | evaluate(my_program, the_global_environment); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function is_self_evaluating(stmt) { 2 | return is_number(stmt) || 3 | is_string(stmt) || 4 | is_boolean(stmt); 5 | } 6 | 7 | const my_program = parse("true; 1;"); 8 | const my_true_statement = list_ref(my_program, 0); 9 | display(is_self_evaluating(my_true_statement)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection4/2.js: -------------------------------------------------------------------------------- 1 | function expt(b,n) { 2 | return expt_iter(b,n,1); 3 | } 4 | function expt_iter(b,counter,product) { 5 | return counter === 0 6 | ? product 7 | : expt_iter(b, 8 | counter - 1, 9 | b * product); 10 | } 11 | 12 | expt(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/8.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function f(x, y) { 5 | function f_helper(a, b) { 6 | return x * square(a) + 7 | y * b + 8 | a * b; 9 | } 10 | return f_helper(1 + x * y, 11 | 1 - y); 12 | } 13 | 14 | f(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection3/4.js: -------------------------------------------------------------------------------- 1 | function is_element_of_set(x,set) { 2 | return ! is_null(set) && 3 | ( x === head(set)) 4 | ? true 5 | : x < head(set) 6 | ? false 7 | : is_element_of_set(x, tail(set)); 8 | } 9 | 10 | is_element_of_set(15, list(10, 15, 20)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/13.js: -------------------------------------------------------------------------------- 1 | w1(20); 2 | const w1 = make_simplified_withdraw(25); 3 | 4 | const w2 = make_simplified_withdraw(25); 5 | function make_simplified_withdraw(balance) { 6 | return amount => { 7 | balance = balance - amount; 8 | return balance; 9 | }; 10 | } 11 | w1(20); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection1/10.js: -------------------------------------------------------------------------------- 1 | function eval_return_statement(stmt, env) { 2 | return make_return_value( 3 | evaluate(return_statement_expression(stmt), 4 | env)); 5 | } 6 | 7 | const my_program = parse("{ function f() { return 1; } f(); }"); 8 | evaluate(my_program, the_global_environment); -------------------------------------------------------------------------------- /docs/md/README_CONTINUATION.md: -------------------------------------------------------------------------------- 1 | CONTINUATION provides the function `call_cc` for generating and consuming continuations. 2 | Click on a name on the right to see how they are defined and used. 3 | 4 | Continuations in Source work similar to the call-with-current-continuation function in Scheme. -------------------------------------------------------------------------------- /docs/specs/source_object_support.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Object Support} 2 | 3 | The following object-processing function is supported: 4 | 5 | \begin{itemize} 6 | \item \lstinline{is_object(x)}: \textit{primitive}, returns 7 | returns \texttt{true} if \texttt{x} is an object, and \texttt{false} if it is not. 8 | \end{itemize} 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/specs/source_standard.tex: -------------------------------------------------------------------------------- 1 | \section{Standard Library} 2 | 3 | The standard library contains constants and functions 4 | that are always available in this language. 5 | The functions indicated as \emph{primitive} are built into the 6 | language implementations. All others are considered 7 | \emph{predeclared} and implemented using the primitive functions. 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection6/7.js: -------------------------------------------------------------------------------- 1 | function fast_expt(b, n) { 2 | return n === 0 3 | ? 1 4 | : is_even(n) 5 | ? square(fast_expt(b, n / 2)) 6 | : b * fast_expt(b, n - 1); 7 | } 8 | function expmod(base, exp, m) { 9 | return fast_expt(base, exp) % m; 10 | } 11 | 12 | expmod(4, 3, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/17.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | function iter(product,counter) { 3 | if (counter > n) { 4 | return product; 5 | } else { 6 | return iter(counter*product, 7 | counter+1); 8 | } 9 | } 10 | return iter(1,1); 11 | } 12 | 13 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/11.js: -------------------------------------------------------------------------------- 1 | function length(items) { 2 | function length_iter(a, count) { 3 | return is_null(a) 4 | ? count 5 | : length_iter(tail(a), count + 1); 6 | } 7 | return length_iter(items, 0); 8 | } 9 | 10 | const odds = list(1, 3, 5, 7); 11 | length(odds); 12 | // returns: 4 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/24.js: -------------------------------------------------------------------------------- 1 | function scale_tree(tree, factor) { 2 | return map(sub_tree => is_pair(sub_tree) 3 | ? scale_tree(sub_tree, factor) 4 | : sub_tree * factor, 5 | tree); 6 | } 7 | 8 | scale_tree(list(1, list(2, list(3, 4), 5), list(6, 7)), 9 | 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/4.js: -------------------------------------------------------------------------------- 1 | const x = pair(pair(1, pair(2,null)), pair(3, pair(4,null))); 2 | function count_leaves(x) { 3 | return is_null(x) 4 | ? 0 5 | : ! is_pair(x) 6 | ? 1 7 | : count_leaves(head(x)) + 8 | count_leaves(tail(x)); 9 | } 10 | count_leaves(x); 11 | // 4 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/7.js: -------------------------------------------------------------------------------- 1 | function accumulate(op, initial, sequence) { 2 | return is_null(sequence) 3 | ? initial 4 | : op(head(sequence), 5 | accumulate(op, initial, tail(sequence))); 6 | } 7 | function plus(x, y) { 8 | return x + y; 9 | } 10 | accumulate(plus, 0, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/8.js: -------------------------------------------------------------------------------- 1 | function accumulate(op, initial, sequence) { 2 | return is_null(sequence) 3 | ? initial 4 | : op(head(sequence), 5 | accumulate(op, initial, tail(sequence))); 6 | } 7 | function times(x, y) { 8 | return x * y; 9 | } 10 | accumulate(times, 1, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/21.js: -------------------------------------------------------------------------------- 1 | function pair(x, y) { 2 | function dispatch(m) { 3 | if (m === "head") { 4 | return x; 5 | } else if (m === "tail") { 6 | return y; 7 | } else { 8 | return "undefined operation -- pair"; 9 | } 10 | } 11 | return dispatch; 12 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection6/4.js: -------------------------------------------------------------------------------- 1 | function f(x) { 2 | function is_even(n) { 3 | return n === 0 4 | ? true 5 | : is_odd(n - 1); 6 | } 7 | function is_odd(n) { 8 | return n === 0 9 | ? false 10 | : is_even(n - 1); 11 | } 12 | return is_even(x); 13 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/13.js: -------------------------------------------------------------------------------- 1 | function is_operation_exp(exp) { 2 | return is_pair(exp) && is_tagged_list(head(exp), "op"); 3 | } 4 | 5 | function operation_exp_op(operation_exp) { 6 | return head(tail(head(operation_exp))); 7 | } 8 | 9 | function operation_exp_operands(operation_exp) { 10 | return tail(operation_exp); 11 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/1.js: -------------------------------------------------------------------------------- 1 | compile_and_go( 2 | parse( 3 | "function factorial(n) { 4 | return n === 1 5 | ? 1 6 | : n * factorial(n - 1); 7 | }")); 8 | 9 | ;;; EC-Eval value: 10 | ok 11 | 12 | ;;; EC-Eval input: 13 | (factorial 5) 14 | ;;; EC-Eval value: 15 | 120 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/9.js: -------------------------------------------------------------------------------- 1 | compile_and_run( 2 | parse( 3 | "function factorial(n) { 4 | return n === 1 5 | ? 1 6 | : n * factorial(n - 1); 7 | }")); 8 | 9 | ;;; EC-Eval value: 10 | ok 11 | 12 | ;;; EC-Eval input: 13 | (factorial 5) 14 | ;;; EC-Eval value: 15 | 120 -------------------------------------------------------------------------------- /docs/specs/source_continuation.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Continuation Support} 2 | \label{conc_supp} 3 | The following functions are supported for generating and consuming continuations: 4 | 5 | \begin{itemize} 6 | \item \texttt{call\_cc(f)}: \(\textit{primitive}\), generates a coninuation \texttt{cont} and calls \texttt{f(cont)}. This is an atomic operation. 7 | \end{itemize} 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/14.js: -------------------------------------------------------------------------------- 1 | w1(20); 2 | w1(20); 3 | const w1 = make_simplified_withdraw(25); 4 | 5 | const w2 = make_simplified_withdraw(25); 6 | function make_simplified_withdraw(balance) { 7 | return amount => { 8 | balance = balance - amount; 9 | return balance; 10 | }; 11 | } 12 | w2(20); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection1/11.js: -------------------------------------------------------------------------------- 1 | function stream_enumerate_interval(low, high) { 2 | return low > high 3 | ? null 4 | : pair(low, 5 | () => stream_enumerate_interval(low + 1, 6 | high)); 7 | } 8 | pair(10001, () => stream_enumerate_interval(10002, 1000000)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection1/9.js: -------------------------------------------------------------------------------- 1 | function stream_enumerate_interval(low, high) { 2 | return low > high 3 | ? null 4 | : pair(low, 5 | () => stream_enumerate_interval(low + 1, 6 | high)); 7 | } 8 | pair(10000, () => stream_enumerate_interval(10001, 1000000)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection3/7.js: -------------------------------------------------------------------------------- 1 | // We use a nullary function as temporary value for names whose 2 | // declaration has not yet been evaluated. The purpose of the 3 | // function definition is purely to create a unique identity; 4 | // the function will never be applied and its return value 5 | // (null) is irrelevant. 6 | const no_value_yet = () => null; -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection4/4.js: -------------------------------------------------------------------------------- 1 | const primitive_constants = list(list("undefined", undefined), 2 | list("NaN", NaN), 3 | list("Infinity", Infinity), 4 | list("math_PI", math_PI) 5 | ); 6 | 7 | primitive_constants; -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/mainpage.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |

8 | 9 | 10 | 11 |
12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/7.js: -------------------------------------------------------------------------------- 1 | const x = pair(pair(1, pair(2,null)), pair(3, pair(4,null))); 2 | function count_leaves(x) { 3 | return is_null(x) 4 | ? 0 5 | : ! is_pair(x) 6 | ? 1 7 | : count_leaves(head(x)) + 8 | count_leaves(tail(x)); 9 | } 10 | count_leaves(list(x, x)); 11 | // 8 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/11.js: -------------------------------------------------------------------------------- 1 | function enumerate_tree(tree) { 2 | return is_null(tree) 3 | ? null 4 | : ! is_pair(tree) 5 | ? list(tree) 6 | : append(enumerate_tree(head(tree)), 7 | enumerate_tree(tail(tree))); 8 | } 9 | 10 | enumerate_tree(list(1, list(2, list(3, 4)), 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/11.js: -------------------------------------------------------------------------------- 1 | function square_of_four(tl, tr, bl, br) { 2 | return painter => stack(beside(tl(painter), tr(painter)), 3 | beside(bl(painter), br(painter))); 4 | } 5 | 6 | show(square_of_four(turn_upside_down, identity, 7 | quarter_turn_right, quarter_turn_left) 8 | (heart) 9 | ); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/5.js: -------------------------------------------------------------------------------- 1 | function make_withdraw_with_balance(balance) { 2 | return amount => { 3 | if (balance >= amount) { 4 | balance = balance - amount; 5 | return balance; 6 | } else { 7 | return "insufficient funds"; 8 | } 9 | }; 10 | } 11 | const w2 = make_withdraw(100); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/3.js: -------------------------------------------------------------------------------- 1 | function sum(term, a, next, b) { 2 | return a > b 3 | ? 0 4 | : term(a) + sum(term, next(a), next, b); 5 | } 6 | function pi_sum(a,b) { 7 | return sum(x => 1.0 / (x * (x + 2)), 8 | a, 9 | x => x + 4, 10 | b); 11 | } 12 | 13 | 8 * pi_sum(1, 1000); -------------------------------------------------------------------------------- /docs/md/README_ARRAYS.md: -------------------------------------------------------------------------------- 1 | ARRAYS provides two useful functions for array processing. 2 | Click on a name on the right to see how they are defined and used. 3 | 4 | Arrays are not covered in 5 | the textbook 6 | Structure and Interpretation 7 | of Computer Programs, JavaScript Adaptation (SICP JS), 8 | but they are included in Source §3. 9 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/3.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return fact_iter(1, 1, n); 3 | } 4 | function fact_iter(product, counter, max_count) { 5 | return counter > max_count 6 | ? product 7 | : fact_iter(counter * product, 8 | counter + 1, 9 | max_count); 10 | } 11 | 12 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/11.js: -------------------------------------------------------------------------------- 1 | function sum(term, a, next, b) { 2 | return a > b 3 | ? 0 4 | : term(a) + sum(term, next(a), next, b); 5 | } 6 | function integral(f, a, b, dx) { 7 | function add_dx(x) { 8 | return x + dx; 9 | } 10 | return sum(f, a + dx / 2, add_dx, b) * dx; 11 | } 12 | 13 | integral(cube, 0, 1, 0.01); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/29.js: -------------------------------------------------------------------------------- 1 | function fold_left(op, initial, sequence) { 2 | function iter(result, rest) { 3 | return is_null(rest) 4 | ? result 5 | : iter(op(result, head(rest)), 6 | tail(rest)); 7 | } 8 | return iter(initial, sequence); 9 | } 10 | fold_left(list, null, list(1, 2, 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function make_withdraw_with_balance(balance) { 2 | return amount => { 3 | if (balance >= amount) { 4 | balance = balance - amount; 5 | return balance; 6 | } else { 7 | return "insufficient funds"; 8 | } 9 | }; 10 | } 11 | const w1 = make_withdraw_with_balance(100); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection2/9.js: -------------------------------------------------------------------------------- 1 | function add_streams(s1, s2) { 2 | return stream_combine((x1, x2) => x1 + x2, s1, s2); 3 | } 4 | const fibs = pair(0, 5 | () => pair(1, 6 | () => add_streams(stream_tail( 7 | fibs)) 8 | ) 9 | ); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/6.js: -------------------------------------------------------------------------------- 1 | function compile_and_go(expression) { 2 | const instructions = assemble(statements(compile(expression, "val", "return")), "eceval"); 3 | the-global-environment = setup-environment(); 4 | set_register_contents("eceval", "val", instructions); 5 | set_register_contents("eceval", "flag", true); 6 | return start("eceval"); 7 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | function cube(x) { 5 | return x * x * x; 6 | } 7 | function p(x) { 8 | return 3 * x - 4 * cube(x); 9 | } 10 | function sine(angle) { 11 | return !(abs(angle) > 0.1) 12 | ? angle 13 | : p(sine(angle / 3.0)); 14 | } 15 | 16 | sine(math_PI / 2); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection4/3.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function is_even(n) { 5 | return n % 2 === 0; 6 | } 7 | function fast_expt(b, n) { 8 | return n === 0 9 | ? 1 10 | : is_even(n) 11 | ? square(fast_expt(b, n / 2)) 12 | : b * fast_expt(b, n - 1); 13 | } 14 | 15 | fast_expt(3, 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/5.js: -------------------------------------------------------------------------------- 1 | function inc(n) { 2 | return n + 1; 3 | } 4 | function sum_cubes(a, b) { 5 | return sum(cube, a, inc, b); 6 | } 7 | function cube(x) { 8 | return x * x * x; 9 | } 10 | function sum(term, a, next, b) { 11 | return a > b 12 | ? 0 13 | : term(a) + sum(term, next(a), next, b); 14 | } 15 | sum_cubes(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/12.js: -------------------------------------------------------------------------------- 1 | function append(list1, list2) { 2 | return is_null(list1) 3 | ? list2 4 | : pair(head(list1), append(tail(list1), list2)); 5 | } 6 | const squares = list(1, 4, 9, 16, 25); 7 | const squares = list(1, 3, 5, 7); 8 | append(squares, odds); 9 | 10 | // returns: [1, [4, [9, [16, [25, [1, [3, [5, [7, null]]]]]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/14.js: -------------------------------------------------------------------------------- 1 | function append(list1, list2) { 2 | return is_null(list1) 3 | ? list2 4 | : pair(head(list1), append(tail(list1), list2)); 5 | } 6 | const squares = list(1, 4, 9, 16, 25); 7 | const squares = list(1, 3, 5, 7); 8 | append(odds, squares); 9 | 10 | // returns: [1, [3, [5, [7, [1, [4, [9, [16, [25, null]]]]]]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/25.js: -------------------------------------------------------------------------------- 1 | function fold_left(op, initial, sequence) { 2 | function iter(result, rest) { 3 | return is_null(rest) 4 | ? result 5 | : iter(op(result, head(rest)), 6 | tail(rest)); 7 | } 8 | return iter(initial, sequence); 9 | } 10 | 11 | fold_left(list, null, list(1, 2, 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/3.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | withdraw(25); // output: 75 12 | withdraw(25); // output: 50 13 | withdraw(60); // output: "Insufficient funds" -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection2/3.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | return fact_iter(1, 1, n); 3 | } 4 | function fact_iter(product, counter, max_count) { 5 | return counter > max_count 6 | ? product 7 | : fact_iter(counter * product, 8 | counter + 1, 9 | max_count); 10 | } 11 | 12 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/6.js: -------------------------------------------------------------------------------- 1 | function make_instruction(text) { 2 | return pair(text, null); 3 | } 4 | 5 | function instruction_text(inst) { 6 | return head(inst); 7 | } 8 | 9 | function instruction_execution_proc(inst) { 10 | return tail(inst); 11 | } 12 | 13 | function set_instruction_execution_proc(inst, proc) { 14 | set_tail(inst, proc); 15 | } -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/examples.tmpl: -------------------------------------------------------------------------------- 1 | 8 |

9 | 10 |
11 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:recommended", ":dependencyDashboard", ":label(dependencies)"], 4 | "packageRules": [ 5 | { 6 | "rangeStrategy": "update-lockfile", 7 | "matchPackageNames": ["*"], 8 | "minimumReleaseAge": "5 days" 9 | } 10 | ], 11 | "enabledManagers": ["npm"] 12 | } 13 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/3.js: -------------------------------------------------------------------------------- 1 | const w1 = make_withdraw_with_balance(100); 2 | function make_withdraw_with_balance(balance) { 3 | return amount => { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "insufficient funds"; 9 | } 10 | }; 11 | } 12 | w1(50); -------------------------------------------------------------------------------- /docs/specs/source_numbers.tex: -------------------------------------------------------------------------------- 1 | \subsection*{\href{https://sourceacademy.org/sicpjs/1.1.1\#p3}{Numbers}} 2 | 3 | We use decimal notation for numbers, with an optional decimal dot. ``Scientific notation'' 4 | (multiplying the number with $10^x$) is indicated with the letter \texttt{e}, followed 5 | by the exponent $x$. 6 | Examples for numbers are \texttt{5432}, \texttt{-5432.109}, and \texttt{-43.21e-45}. 7 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/4.js: -------------------------------------------------------------------------------- 1 | function cube(x) { 2 | return x * x * x; 3 | } 4 | function sum(term, a, next, b) { 5 | return a > b 6 | ? 0 7 | : term(a) + sum(term, next(a), next, b); 8 | } 9 | function inc(n) { 10 | return n + 1; 11 | } 12 | function sum_cubes(a, b) { 13 | return sum(cube, a, inc, b); 14 | } 15 | 16 | sum_cubes(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/8.js: -------------------------------------------------------------------------------- 1 | function sum_integers(a, b) { 2 | return sum(identity, a, inc, b); 3 | } 4 | function sum(term, a, next, b) { 5 | return a > b 6 | ? 0 7 | : term(a) + sum(term, next(a), next, b); 8 | } 9 | function inc(n) { 10 | return n + 1; 11 | } 12 | function identity(x) { 13 | return x; 14 | } 15 | sum_integers(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/9.js: -------------------------------------------------------------------------------- 1 | function print_rat(x) { 2 | display(numer(x)); 3 | display("-"); 4 | display(denom(x)); 5 | } 6 | function make_rat(n, d) { 7 | return pair(n, d); 8 | } 9 | function numer(x) { 10 | return head(x); 11 | } 12 | function denom(x) { 13 | return tail(x); 14 | } 15 | const one_half = make_rat(1, 2); 16 | 17 | print_rat(one_half); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function pair(x, y) { 2 | return m => 3 | m === 0 4 | ? x 5 | : m === 1 6 | ? y 7 | : error(m, "Argument not 0 or 1 in pair"); 8 | } 9 | function head(z) { 10 | return z(0); 11 | } 12 | function tail(z) { 13 | return z(1); 14 | } 15 | 16 | const x = pair(1,2); 17 | head(x); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/6.js: -------------------------------------------------------------------------------- 1 | function make_withdraw(initial_amount) { 2 | let balance = initial_amount; 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "insufficient funds"; 9 | } 10 | } 11 | return withdraw; 12 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection1/3.js: -------------------------------------------------------------------------------- 1 | function is_prime(n) { 2 | return n === smallest_divisor(n); 3 | } 4 | function enumerate_interval(low, high) { 5 | return low > high 6 | ? null 7 | : pair(low, 8 | enumerate_interval(low + 1, high)); 9 | } 10 | head(tail(filter(is_prime, 11 | enumerate_interval(10000, 1000000)))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/7.js: -------------------------------------------------------------------------------- 1 | function sum(term, a, next, b) { 2 | return a > b 3 | ? 0 4 | : term(a) + sum(term, next(a), next, b); 5 | } 6 | function inc(n) { 7 | return n + 1; 8 | } 9 | function identity(x) { 10 | return x; 11 | } 12 | function sum_integers(a, b) { 13 | return sum(identity, a, inc, b); 14 | } 15 | 16 | sum_integers(1, 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/10.js: -------------------------------------------------------------------------------- 1 | function print_rat(x) { 2 | display(numer(x)); 3 | display("-"); 4 | display(denom(x)); 5 | } 6 | function make_rat(n, d) { 7 | return pair(n, d); 8 | } 9 | function numer(x) { 10 | return head(x); 11 | } 12 | function denom(x) { 13 | return tail(x); 14 | } 15 | const one_third = make_rat(1, 3); 16 | 17 | print_rat(one_third); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection1/8.js: -------------------------------------------------------------------------------- 1 | function make_rat(n, d) { 2 | return pair(n, d); 3 | } 4 | function numer(x) { 5 | return head(x); 6 | } 7 | function denom(x) { 8 | return tail(x); 9 | } 10 | function print_rat(x) { 11 | display(numer(x)); 12 | display("-"); 13 | display(denom(x)); 14 | } 15 | 16 | const one_half = make_rat(1, 2); 17 | 18 | print_rat(one_half); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection2/23.js: -------------------------------------------------------------------------------- 1 | function scale_tree(tree, factor) { 2 | return is_null(tree) 3 | ? null 4 | : ! is_pair(tree) 5 | ? tree * factor 6 | : pair(scale_tree(head(tree), factor), 7 | scale_tree(tail(tree), factor)); 8 | } 9 | 10 | scale_tree(list(1, list(2, list(3, 4), 5), list(6, 7)), 11 | 10); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/22.js: -------------------------------------------------------------------------------- 1 | function accumulate_n(op, init, seqs) { 2 | return is_null(head(seqs)) 3 | ? null 4 | : pair(accumulate(op, init, ??), 5 | accumulate_n(op, init, ??)); 6 | } 7 | 8 | const seq_seq = list(list(1, 2, 3), list(4, 5, 6), 9 | list(7, 8, 9), list(10, 11, 12)); 10 | accumulate_n(add, 0, seq_seq); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/11.js: -------------------------------------------------------------------------------- 1 | function mystery(x) { 2 | function loop(x, y) { 3 | if (is_null(x)) { 4 | return y; 5 | } else { 6 | let temp = tail(x); 7 | set_tail(x, y); 8 | return loop(temp, x); 9 | } 10 | } 11 | return loop(x, null); 12 | } 13 | const v = list("a", "b", "c"); 14 | const w = mystery(v); -------------------------------------------------------------------------------- /docs/md/README_BINARYTREES.md: -------------------------------------------------------------------------------- 1 | BINARYTREES provide functions for binary trees, as covered 2 | the textbook 3 | Structure and Interpretation 4 | of Computer Programs, JavaScript Adaptation (SICP JS) 5 | in 6 | section 2.3.3 Example: Representing Sets. 7 | Click on a name on the right to see how they are defined and used. 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/37.js: -------------------------------------------------------------------------------- 1 | function flatmap(f, seq) { 2 | return accumulate(append, null, map(f, seq)); 3 | } 4 | function permutations(s) { 5 | return is_null(s) 6 | ? list(null) 7 | : flatmap(x => map(p => pair(x, p), 8 | permutations(remove(x, s))), 9 | s); 10 | } 11 | 12 | permutations(list(1, 2, 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection3/18.js: -------------------------------------------------------------------------------- 1 | function factorial(n) { 2 | let product = 1; 3 | let counter = 1; 4 | function iter() { 5 | if (counter > n) { 6 | return product; 7 | } else { 8 | product = counter * product; 9 | counter = counter + 1; 10 | return iter(); 11 | } 12 | } 13 | return iter(); 14 | } 15 | 16 | factorial(5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/9.js: -------------------------------------------------------------------------------- 1 | const v = list("a", "b", "c"); 2 | function mystery(x) { 3 | function loop(x, y) { 4 | if (is_null(x)) { 5 | return y; 6 | } else { 7 | let temp = tail(x); 8 | set_tail(x, y); 9 | return loop(temp, x); 10 | } 11 | } 12 | return loop(x, null); 13 | } 14 | 15 | const w = mystery(v); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection6/3.js: -------------------------------------------------------------------------------- 1 | function is_even(n) { 2 | return n % 2 === 0; 3 | } 4 | function square(x) { 5 | return x * x; 6 | } 7 | function expmod(base, exp, m) { 8 | return exp === 0 9 | ? 1 10 | : is_even(exp) 11 | ? square(expmod(base, exp / 2, m)) % m 12 | : (base * expmod(base, exp - 1, m)) % m; 13 | } 14 | 15 | expmod(4, 3, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section4/subsection3/7.js: -------------------------------------------------------------------------------- 1 | deriv(list("*", list("*", "x", "y"), list("+", "x", 4)), "x"); 2 | // [ "+", 3 | // [["*", [["*", ["x", ["y", null]]], 4 | // [["+", [1, [0, null]]], null]]], 5 | // [["*", 6 | // [["+", 7 | // [["*", ["x", [0, null]]], 8 | // [["*", [1, ["y", null]]], null]]], 9 | // [["+", ["x", [4, null]]], null] ] ], 10 | // null ]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection1/5.js: -------------------------------------------------------------------------------- 1 | function eval_function_definition(stmt,env) { 2 | return make_compound_function( 3 | map(name_of_name, 4 | function_definition_parameters(stmt)), 5 | function_definition_body(stmt), 6 | env); 7 | } 8 | 9 | const my_fun = parse("x => x * x;"); 10 | eval_function_definition(my_fun, the_empty_environment); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/returns.tmpl: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 | 9 | 10 | 11 |
12 |
13 | Type 14 |
15 |
16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /docs/specs/source_python_numbers.tex: -------------------------------------------------------------------------------- 1 | \subsection*{\href{https://sourceacademy.org/sicpjs/1.1.1\#p3}{Floating-point Numbers}} 2 | 3 | We use decimal notation for numbers, with an optional decimal dot. ``Scientific notation'' 4 | (multiplying the number with $10^x$) is indicated with the letter \texttt{e}, followed 5 | by the exponent $x$. 6 | Examples for numbers are \texttt{5432}, \texttt{-5432.109}, and \texttt{-43.21e-45}. 7 | 8 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/4.js: -------------------------------------------------------------------------------- 1 | let balance = 100; 2 | 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "Insufficient funds"; 9 | } 10 | } 11 | withdraw(25); // output: 75 12 | withdraw(25); // output: 50 13 | withdraw(60); // output: "Insufficient funds" 14 | withdraw(15); // output: 35 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function front_ptr(queue) { 2 | return head(queue); 3 | } 4 | function rear_ptr(queue) { 5 | return tail(queue); 6 | } 7 | function set_front_ptr(queue, item) { 8 | set_head(queue, item); 9 | } 10 | function set_rear_ptr(queue, item) { 11 | set_tail(queue, item); 12 | } 13 | function is_empty_queue(queue) { 14 | return is_null(front_ptr(queue)); 15 | } -------------------------------------------------------------------------------- /docs/specs/source_2_stepper.tex: -------------------------------------------------------------------------------- 1 | \input source_header.tex 2 | 3 | \begin{document} 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | \docheader{2022}{Source}{\S 2 Stepper}{Martin Henz, Tan Yee Jian, Zhang Xinyi, Zhao Jingjing, \\ Zachary Chua, Peter Jung, Poomklao Teerawatthanaprapha, \\ Hao Sitong} 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | 8 | \input source_2_stepper_rules 9 | 10 | \end{document} 11 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/15.js: -------------------------------------------------------------------------------- 1 | function number_equal(exp, num) { 2 | return is_number(exp) && exp === num; 3 | } 4 | function make_sum(a1, a2) { 5 | return number_equal(a1, 0) 6 | ? a2 7 | : number_equal(a2, 0) 8 | ? a1 9 | : is_number(a1) && is_number(a2) 10 | ? a1 + a2 11 | : list("+", a1, a2); 12 | } 13 | 14 | make_sum(2, 3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection4/1.js: -------------------------------------------------------------------------------- 1 | function make_leaf(symbol, weight) { 2 | return list("leaf", symbol, weight); 3 | } 4 | function is_leaf(object) { 5 | return head(object) === "leaf"; 6 | } 7 | function symbol_leaf(x) { 8 | return head(tail(x)); 9 | } 10 | function weight_leaf(x) { 11 | return head(tail(tail(x))); 12 | } 13 | 14 | const my_leaf = make_leaf("A", 8); 15 | 16 | weight_leaf(my_leaf); -------------------------------------------------------------------------------- /src/repl/main.ts: -------------------------------------------------------------------------------- 1 | import { Command } from '@commander-js/extra-typings' 2 | 3 | import { getSVMCCommand } from './svmc' 4 | import { getReplCommand } from './repl' 5 | import { getTranspilerCommand } from './transpiler' 6 | 7 | export const getMainCommand = () => 8 | new Command() 9 | .addCommand(getSVMCCommand()) 10 | .addCommand(getTranspilerCommand()) 11 | .addCommand(getReplCommand(), { isDefault: true }) 12 | -------------------------------------------------------------------------------- /docs/specs/source_arrays.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Arrays} 2 | 3 | Arrays in Source are created using literal array expressions: 4 | \begin{lstlisting} 5 | let my_array_1 = []; 6 | let my_array_2 = [42, 71, 13]; 7 | \end{lstlisting} 8 | Array access of the form $a$\lstinline{[}$i$\lstinline{]} has constant time complexity $\Theta(1)$. 9 | Array assignment the form $a$\lstinline{[}$n$\lstinline{] = }$x$ has a time complexity 10 | $O(n)$. 11 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/8.js: -------------------------------------------------------------------------------- 1 | function make_withdraw_with_balance(balance) { 2 | return amount => { 3 | if (balance >= amount) { 4 | balance = balance - amount; 5 | return balance; 6 | } else { 7 | return "insufficient funds"; 8 | } 9 | }; 10 | } 11 | const w1 = make_withdraw_with_balance(100); 12 | const w2 = make_withdraw_with_balance(100); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/10.js: -------------------------------------------------------------------------------- 1 | function pi_sum(a, b) { 2 | function pi_term(x) { 3 | return 1.0 / (x * (x + 2)); 4 | } 5 | function pi_next(x) { 6 | return x + 4; 7 | } 8 | return sum(pi_term, a, pi_next, b); 9 | } 10 | function sum(term, a, next, b) { 11 | return a > b 12 | ? 0 13 | : term(a) + sum(term, next(a), next, b); 14 | } 15 | 8 * pi_sum(1, 1000); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/12.js: -------------------------------------------------------------------------------- 1 | function cube(x) { 2 | return x * x * x; 3 | } 4 | function integral(f, a, b, dx) { 5 | function add_dx(x) { 6 | return x + dx; 7 | } 8 | return sum(f, a + dx / 2, add_dx, b) * dx; 9 | } 10 | function sum(term, a, next, b) { 11 | return a > b 12 | ? 0 13 | : term(a) + sum(term, next(a), next, b); 14 | } 15 | integral(cube, 0, 1, 0.01); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/13.js: -------------------------------------------------------------------------------- 1 | function cube(x) { 2 | return x * x * x; 3 | } 4 | function integral(f, a, b, dx) { 5 | function add_dx(x) { 6 | return x + dx; 7 | } 8 | return sum(f, a + dx / 2, add_dx, b) * dx; 9 | } 10 | function sum(term, a, next, b) { 11 | return a > b 12 | ? 0 13 | : term(a) + sum(term, next(a), next, b); 14 | } 15 | integral(cube, 0, 1, 0.005); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/27.js: -------------------------------------------------------------------------------- 1 | function fold_left(op, initial, sequence) { 2 | function iter(result, rest) { 3 | return is_null(rest) 4 | ? result 5 | : iter(op(result, head(rest)), 6 | tail(rest)); 7 | } 8 | return iter(initial, sequence); 9 | } 10 | function divide(x, y) { 11 | return x / y; 12 | } 13 | fold_left(divide, 1, list(1, 2, 3)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/6.js: -------------------------------------------------------------------------------- 1 | function make_withdraw() { 2 | let balance = 100; 3 | return amount => { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "insufficient funds"; 9 | } 10 | }; 11 | } 12 | const new_withdraw = make_withdraw(); 13 | 14 | new_withdraw(60); 15 | new_withdraw(60); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection3/4.js: -------------------------------------------------------------------------------- 1 | function enclosing_environment(env) { 2 | return tail(env); 3 | } 4 | function first_frame(env) { 5 | return head(env); 6 | } 7 | function enclose_by(frame, env) { 8 | return pair(frame, env); 9 | } 10 | const the_empty_environment = null; 11 | function is_empty_environment(env) { 12 | return is_null(env); 13 | } 14 | 15 | is_empty_environment(the_empty_environment); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.js 3 | 4 | # docs 5 | !docs/jsdoc/templates/**/*.js 6 | !docs/lib/**/*.js 7 | docs/source 8 | 9 | *.map 10 | dist/ 11 | .idea/ 12 | coverage/ 13 | 14 | # emacs backup files 15 | *~ 16 | .DS_Store 17 | 18 | .vscode/ 19 | *.tsbuildinfo 20 | test-report 21 | 22 | # yarn files 23 | 24 | .yarn 25 | !.yarn/patches 26 | !.yarn/plugins 27 | !.yarn/releases 28 | !.yarn/sdks 29 | !.yarn/versions 30 | yarn-error.log 31 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection1/9.js: -------------------------------------------------------------------------------- 1 | function sum(term, a, next, b) { 2 | return a > b 3 | ? 0 4 | : term(a) + sum(term, next(a), next, b); 5 | } 6 | function pi_sum(a, b) { 7 | function pi_term(x) { 8 | return 1.0 / (x * (x + 2)); 9 | } 10 | function pi_next(x) { 11 | return x + 4; 12 | } 13 | return sum(pi_term, a, pi_next, b); 14 | } 15 | 16 | 8 * pi_sum(1, 1000); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/32.js: -------------------------------------------------------------------------------- 1 | function enumerate_interval(low, high) { 2 | return low > high 3 | ? null 4 | : pair(low, 5 | enumerate_interval(low + 1, high)); 6 | } 7 | const n = 6; 8 | accumulate(append, 9 | null, 10 | map(i => map(j => list(i, j), 11 | enumerate_interval(1, i-1)), 12 | enumerate_interval(1, n))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function is_tagged_list(stmt, the_tag) { 2 | return is_pair(stmt) && head(stmt) === the_tag; 3 | } 4 | function is_name(stmt) { 5 | return is_tagged_list(stmt, "name"); 6 | } 7 | function name_of_name(stmt) { 8 | return head(tail(stmt)); 9 | } 10 | 11 | const my_name_statement = parse("x;"); 12 | display(is_name(my_name_statement)); 13 | display(name_of_name(my_name_statement)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/7.js: -------------------------------------------------------------------------------- 1 | compile_and_go( 2 | parse( 3 | "function factorial(n) { 4 | return n === 1 5 | ? 1 6 | : n * factorial(n - 1); 7 | }")); 8 | 9 | (total-pushes = 0 maximum-depth = 0) 10 | ;;; EC-Eval value: 11 | ok 12 | 13 | ;;; EC-Eval input: 14 | (factorial 5) 15 | (total-pushes = 31 maximum-depth = 14) 16 | ;;; EC-Eval value: 17 | 120 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/5.js: -------------------------------------------------------------------------------- 1 | function filter(predicate, sequence) { 2 | return is_null(sequence) 3 | ? null 4 | : predicate(head(sequence)) 5 | ? pair(head(sequence), 6 | filter(predicate, tail(sequence))) 7 | : filter(predicate, tail(sequence)); 8 | } 9 | function is_odd(n) { 10 | return n % 2 === 1; 11 | } 12 | filter(is_odd, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/12.js: -------------------------------------------------------------------------------- 1 | function square_of_four(tl, tr, bl, br) { 2 | return painter => stack(beside(tl(painter), tr(painter)), 3 | beside(bl(painter), br(painter))); 4 | } 5 | function identity(x) { 6 | return x; 7 | } 8 | const flipped_pairs = 9 | square_of_four(turn_upside_down, flip_vert, 10 | flip_horiz, identity); 11 | 12 | show(flipped_pairs(heart)); -------------------------------------------------------------------------------- /docs/jsdoc/templates/template/tmpl/tutorial.tmpl: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 0) { ?> 5 |
    8 |
  • 9 |
10 | 11 | 12 |

13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /docs/md/README_MCE.md: -------------------------------------------------------------------------------- 1 | MCE provides two useful functions for working with the 2 | meta-circular evaluator of Source. It also provides a Source lexer (tokeniser). 3 | Click on a name on the right to see how they are defined and used. 4 | 5 | The meta-circular evaluator of Source is covered in chapter 4 of 6 | the textbook 7 | Structure and Interpretation 8 | of Computer Programs, JavaScript Adaptation (SICP JS). 9 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/4.js: -------------------------------------------------------------------------------- 1 | function filter(predicate, sequence) { 2 | return is_null(sequence) 3 | ? null 4 | : predicate(head(sequence)) 5 | ? pair(head(sequence), 6 | filter(predicate, tail(sequence))) 7 | : filter(predicate, tail(sequence)); 8 | } 9 | 10 | function is_odd(n) { 11 | return n % 2 === 1; 12 | } 13 | filter(is_odd, list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /docs/md/README_PAIRMUTATORS.md: -------------------------------------------------------------------------------- 1 | PAIRMUTATORS provides two functions for changing pairs. 2 | Click on a name on the right to see how they are defined and used. 3 | 4 | Pair mutation is covered in 5 | the textbook 6 | Structure and Interpretation 7 | of Computer Programs, JavaScript Adaptation (SICP JS) 8 | in 9 | section 3.3.1 Mutable List Structure. 10 | 11 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/14.js: -------------------------------------------------------------------------------- 1 | function is_even(n) { 2 | return n % 2 === 0; 3 | } 4 | function expmod(base, exp, m) { 5 | const to_half = expmod(base, exp / 2, m); 6 | return exp === 0 7 | ? 1 8 | : is_even(exp) 9 | ? to_half * to_half 10 | % m 11 | : base 12 | * expmod(base, exp - 1, m) 13 | % m; 14 | } 15 | 16 | expmod(4, 3, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/9.js: -------------------------------------------------------------------------------- 1 | const w1 = make_withdraw_with_balance(100); 2 | const w2 = make_withdraw_with_balance(100); 3 | function make_withdraw_with_balance(balance) { 4 | return amount => { 5 | if (balance >= amount) { 6 | balance = balance - amount; 7 | return balance; 8 | } else { 9 | return "insufficient funds"; 10 | } 11 | }; 12 | } 13 | w1(50); // output: 50 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection6/8.js: -------------------------------------------------------------------------------- 1 | function is_even(n) { 2 | return n % 2 === 0; 3 | } 4 | function expmod(base, exp, m) { 5 | return exp === 0 6 | ? 1 7 | : is_even(exp) 8 | ? expmod(base, exp / 2, m) 9 | * expmod(base, exp / 2, m) 10 | % m 11 | : base 12 | * expmod(base, exp - 1, m) 13 | % m; 14 | } 15 | 16 | expmod(4, 3, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/12.js: -------------------------------------------------------------------------------- 1 | function is_even(n) { 2 | return n % 2 === 0; 3 | } 4 | function expmod(base, exp, m) { 5 | return exp === 0 6 | ? 1 7 | : is_even(exp) 8 | ? expmod(base, exp / 2, m) 9 | * expmod(base, exp / 2, m) 10 | % m 11 | : base 12 | * expmod(base, exp - 1, m) 13 | % m; 14 | } 15 | 16 | expmod(4, 3, 5); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection1/3.js: -------------------------------------------------------------------------------- 1 | function list_of_values(exps, env) { 2 | if (no_operands(exps)) { 3 | return null; 4 | } else { 5 | return pair(evaluate(first_operand(exps), env), 6 | list_of_values(rest_operands(exps), env)); 7 | } 8 | } 9 | 10 | const my_addition_expression = parse("1 + 2;"); 11 | list_of_values(list(1, my_addition_expression, 7), 12 | the_global_environment); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section1/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function sqrt(x) { 2 | function good_enough(guess, x) { 3 | return abs(square(guess) - x) < 0.001; 4 | } 5 | function improve(guess, x) { 6 | return average(guess, x / guess); 7 | } 8 | function sqrt_iter(guess, x) { 9 | return good_enough(guess, x) 10 | ? guess 11 | : sqrt_iter(improve(guess, x), x); 12 | } 13 | return sqrt_iter(1.0); 14 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/4.js: -------------------------------------------------------------------------------- 1 | function user_print(object) { 2 | if (compound_procedure(object)) { 3 | display(list( 4 | "compound_procedure", 5 | procedure_parameters(object), 6 | procedure_body(object), 7 | "")); 8 | } else if (compiled_procedure(object)) { 9 | display(""); 10 | } else { 11 | display(object); 12 | } 13 | } -------------------------------------------------------------------------------- /docs/specs/source_import.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Import directives} 2 | 3 | Import directives allow programs to import values from modules and bind them to names, whose scope 4 | is the entire program in which the import directive occurs. Import directives can only appear at the top-level. All names that appear in import directives 5 | must be distinct, and must also be distinct from all top-level variables. The Source specifications do not specify how modules are 6 | programmed. 7 | -------------------------------------------------------------------------------- /docs/specs/source_python_import.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Import directives} 2 | 3 | Import directives allow programs to import values from modules and bind them to names, whose scope 4 | is the entire program in which the import directive occurs. Import directives can only appear at the top-level. All names that appear in import directives 5 | must be distinct, and must also be distinct from all top-level variables. The specifications do not specify how modules are 6 | programmed. 7 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/4.js: -------------------------------------------------------------------------------- 1 | function sum(term, a, next, b) { 2 | return a > b 3 | ? 0 4 | : term(a) + sum(term, next(a), next, b); 5 | } 6 | function cube(x) { 7 | return x * x * x; 8 | } 9 | function integral(f, a, b, dx) { 10 | return sum(f, 11 | a + dx / 2.0, 12 | x => x + dx, 13 | b) 14 | * 15 | dx; 16 | } 17 | 18 | integral(cube, 0, 1, 0.01); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/17.js: -------------------------------------------------------------------------------- 1 | function map(f, sequence) { 2 | return accumulate((x, y) => ?? , 3 | null, sequence); 4 | } 5 | 6 | function append(seq1, seq2) { 7 | return accumulate(pair, ??, ??); 8 | } 9 | 10 | function length(sequence) { 11 | return accumulate(??, 0, sequence); 12 | } 13 | 14 | map_(math_sqrt, list(1, 2, 3, 4)); 15 | // append_(list(1, 2, 3), list(4, 5, 6)); 16 | // length_(list(1, 2, 3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection5/1.js: -------------------------------------------------------------------------------- 1 | function stream_withdraw(balance, amount_stream) { 2 | return pair(balance, 3 | () => stream_withdraw( 4 | balance - head(amount_stream), 5 | stream_tail(amount_stream))); 6 | } 7 | 8 | const my_amounts = list_to_stream(list(50, 100, 40)); 9 | const my_account_stream = stream_withdraw(200, my_amounts); 10 | eval_stream(my_account_stream, 3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function is_equal(a, b) { 2 | return (is_pair(a) && is_pair(b) && 3 | is_equal(head(a), head(b)) && is_equal(tail(a), tail(b))) 4 | || 5 | a === b; 6 | } 7 | function assoc(key, records) { 8 | return is_null(records) 9 | ? undefined 10 | : is_equal(key, head(head(records))) 11 | ? head(records) 12 | : assoc(key, tail(records)); 13 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/12.js: -------------------------------------------------------------------------------- 1 | function make_operation_exp(exp, machine, labels, operations) { 2 | const op = lookup_prim(operation_exp_op(exp), operations); 3 | const aprocs = map(e => make_primitive_exp(e, machine, labels), 4 | operation_exp_operands(exp)); 5 | 6 | function perform_make_operation_exp() { 7 | return op(map(p => p(), aprocs)); 8 | } 9 | 10 | return perform_make_operation_exp; 11 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section2/subsection3/7.js: -------------------------------------------------------------------------------- 1 | function make_withdraw(initial_amount) { 2 | let balance = initial_amount; 3 | function withdraw(amount) { 4 | if (balance >= amount) { 5 | balance = balance - amount; 6 | return balance; 7 | } else { 8 | return "insufficient funds"; 9 | } 10 | } 11 | return withdraw; 12 | } 13 | const w1 = make_withdraw(100); 14 | w1(50); 15 | const w2 = make_withdraw(100); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section5/subsection1/18.js: -------------------------------------------------------------------------------- 1 | function stream_enumerate_interval(low, high) { 2 | return low > high 3 | ? null 4 | : pair(low, 5 | () => stream_enumerate_interval(low + 1, 6 | high)); 7 | } 8 | function show(x) { 9 | display(x); 10 | return x; 11 | } 12 | let x = stream_map(show, stream_enumerate_interval(0, 10)); 13 | stream_ref(x, 5); 14 | stream_ref(x, 7); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection1/10.js: -------------------------------------------------------------------------------- 1 | function A(x,y) { 2 | return y === 0 3 | ? 0 4 | : x === 0 5 | ? 2 * y 6 | : y === 1 7 | ? 2 8 | : A(x - 1, A(x, y - 1)); 9 | } 10 | function f(n) { 11 | return A(0, n); 12 | } 13 | function g(n) { 14 | return A(1, n); 15 | } 16 | function h(n) { 17 | return A(2, n); 18 | } 19 | function k(n) { 20 | return 5 * n * n; 21 | } 22 | 23 | k(4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/10.js: -------------------------------------------------------------------------------- 1 | w1(50); // output: 50 2 | const w1 = make_withdraw_with_balance(100); 3 | const w2 = make_withdraw_with_balance(100); 4 | function make_withdraw_with_balance(balance) { 5 | return amount => { 6 | if (balance >= amount) { 7 | balance = balance - amount; 8 | return balance; 9 | } else { 10 | return "insufficient funds"; 11 | } 12 | }; 13 | } 14 | w2(70); // output: 30 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection2/15.js: -------------------------------------------------------------------------------- 1 | function is_even(n) { 2 | return n % 2 === 0; 3 | } 4 | function expmod(base, exp, m) { 5 | if (exp === 0) { 6 | return 1; 7 | } else { 8 | if (is_even(exp)) { 9 | const to_half = expmod(base, exp / 2, m); 10 | return to_half * to_half % m; 11 | } else { 12 | return base * expmod(base, exp - 1, m) % m; 13 | } 14 | } 15 | } 16 | 17 | expmod(4, 3, 5); -------------------------------------------------------------------------------- /docs/specs/Makefile: -------------------------------------------------------------------------------- 1 | PDFLATEX = latexmk -pdf 2 | 3 | SPECSNUMS = 1 1_wasm 1_type_inference 1_infinite_loop_detection 1_typed 2 2_typed 3_type_inference 3 3_typed 4 4_explicitcontrol 4_typed styleguide 2_stepper studio_2 python_1 4 | 5 | SPECS = $(SPECSNUMS:%=source_%) 6 | 7 | PDFSPECS = $(SPECS:%=%.pdf) 8 | 9 | HELPERSTEX = $(HELPERS:%=source_%.tex) 10 | 11 | all: $(PDFSPECS) 12 | 13 | %.pdf: %.tex 14 | $(PDFLATEX) $* 15 | 16 | clean: 17 | rm -f *~ *.dvi *.aux *.log *.ps *.out *.pdf 18 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/2.js: -------------------------------------------------------------------------------- 1 | // The textbook proposes a primitive function get_new_pair. 2 | // Since JavaScript does not provide such a function, let's 3 | // define it as follows, for the sake of the example. 4 | 5 | function get_new_pair() { 6 | return pair(undefined, undefined); 7 | } 8 | function pair(x, y) { 9 | const fresh = get_new_pair(); 10 | set_head(fresh, x); 11 | set_tail(fresh, y); 12 | return fresh; 13 | } 14 | 15 | pair(pair(1, 2), 4); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection1/4.js: -------------------------------------------------------------------------------- 1 | function eval_conditional_expression(stmt, env) { 2 | return is_true(evaluate(cond_expr_pred(stmt), 3 | env)) 4 | ? evaluate(cond_expr_cons(stmt), 5 | env) 6 | : evaluate(cond_expr_alt(stmt), 7 | env); 8 | } 9 | 10 | const my_cond_expr = parse("if (true) { 1; } else { 2; }"); 11 | eval_conditional_expression(my_cond_expr, the_empty_environment); -------------------------------------------------------------------------------- /docs/lib/pairmutator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * changes the pair p such that its head is x. 3 | * @param {pair} p - given pair 4 | * @param {value} x - given value 5 | * @returns {undefined} undefined 6 | */ 7 | function set_head(p, x) {} 8 | 9 | /** 10 | * changes the pair p such that its tail is x. 11 | * @param {pair} p - given pair 12 | * @param {value} x - given value 13 | * @returns {undefined} undefined 14 | */ 15 | function set_tail(p, x) {} 16 | -------------------------------------------------------------------------------- /src/tracer/index.ts: -------------------------------------------------------------------------------- 1 | import { StepperBaseNode } from './interface' 2 | 3 | export let redex: { preRedex: StepperBaseNode[]; postRedex: StepperBaseNode[] } = { 4 | preRedex: [], 5 | postRedex: [] 6 | } 7 | 8 | export interface Marker { 9 | redex?: StepperBaseNode | null // area of highlighted ast 10 | redexType?: 'beforeMarker' | 'afterMarker' 11 | explanation?: string 12 | } 13 | 14 | export interface IStepperPropContents { 15 | ast: StepperBaseNode 16 | markers?: Marker[] 17 | } 18 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection2/10.js: -------------------------------------------------------------------------------- 1 | function is_tagged_list(stmt, the_tag) { 2 | return is_pair(stmt) && head(stmt) === the_tag; 3 | } 4 | function is_block(stmt) { 5 | return is_tagged_list(stmt, "block"); 6 | } 7 | function make_block(stmt) { 8 | return list("block", stmt); 9 | } 10 | function block_body(stmt) { 11 | return head(tail(stmt)); 12 | } 13 | 14 | const my_block = parse("{ 1; true; 45; }"); 15 | display(is_block(my_block)); 16 | display(block_body(my_block)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function is_odd(n) { 5 | return n % 2 === 1; 6 | } 7 | function sum_odd_squares(tree) { 8 | return is_null(tree) 9 | ? 0 10 | : ! is_pair(tree) 11 | ? (is_odd(tree) ? square(tree) : 0) 12 | : sum_odd_squares(head(tree)) 13 | + 14 | sum_odd_squares(tail(tree)); 15 | } 16 | 17 | sum_odd_squares(list(list(2, 3), list(4, 5))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/15.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function is_odd(n) { 5 | return n % 2 === 1; 6 | } 7 | function times(x, y) { 8 | return x * y; 9 | } 10 | function product_of_squares_of_odd_elements(sequence) { 11 | return accumulate(times, 12 | 1, 13 | map(square, 14 | filter(is_odd, sequence))); 15 | } 16 | 17 | product_of_squares_of_odd_elements(list(1, 2, 3, 4, 5)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection3/1.js: -------------------------------------------------------------------------------- 1 | function is_equal(a, b) { 2 | return (is_pair(a) && is_pair(b) && 3 | is_equal(head(a), head(b)) && is_equal(tail(a), tail(b))) 4 | || 5 | a === b; 6 | } 7 | function is_element_of_set(x, set) { 8 | return ! is_null(set) && 9 | ( is_equal(x, head(set)) || 10 | is_element_of_set(x, tail(set)) ); 11 | } 12 | 13 | is_element_of_set(15, 14 | adjoin_set(10, adjoin_set(15, adjoin_set(20, null)))); -------------------------------------------------------------------------------- /src/modules/__tests__/moduleUtils.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from 'vitest' 2 | import { isSourceModule } from '../utils' 3 | 4 | describe(isSourceModule, () => { 5 | test.each([ 6 | ['Relative paths are not source modules', './module.js', false], 7 | ['Absolute paths are not source modules', '/module.js', false], 8 | ['Bare paths are source modules', 'module.js', true] 9 | ])('%#: %s', (_, moduleName, expected) => expect(isSourceModule(moduleName)).toEqual(expected)) 10 | }) 11 | -------------------------------------------------------------------------------- /docs/md/README_STREAMS.md: -------------------------------------------------------------------------------- 1 | The functions in STREAMS provide useful functions for stream processing, 2 | as introduced on 3 | section 4 | 3.5 Stream Processing 5 | of the textbook 6 | Structure and Interpretation 7 | of Computer Programs, JavaScript Adaptation (SICP JS). 8 | 9 | On the right, you see all predeclared STREAMS functions, 10 | in alphabetical 11 | order. Click on a name to see how it is defined and used. 12 | -------------------------------------------------------------------------------- /docs/specs/source_pair_mutators.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Pair Mutators} 2 | 3 | The following pair mutator functions are supported: 4 | 5 | \begin{itemize} 6 | \item \lstinline{set_head(p, x)}: \textit{primitive}, changes the pair \lstinline{p} such that its head is \lstinline{x}. 7 | Returns \lstinline{undefined}. 8 | \item \lstinline{set_tail(p, x)}: \textit{primitive}, changes the pair \lstinline{p} such that its tail is \lstinline{x}. 9 | Returns \lstinline{undefined}. 10 | \end{itemize} 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection6/1.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | function smallest_divisor(n) { 5 | return find_divisor(n, 2); 6 | } 7 | function find_divisor(n, test_divisor) { 8 | return square(test_divisor) > n 9 | ? n 10 | : divides(test_divisor, n) 11 | ? test_divisor 12 | : find_divisor(n, test_divisor + 1); 13 | } 14 | function divides(a, b) { 15 | return b % a === 0; 16 | } 17 | 18 | smallest_divisor(42); -------------------------------------------------------------------------------- /docs/specs/source_intro.tex: -------------------------------------------------------------------------------- 1 | The language Source is the official language of the textbook 2 | \href{https://sourceacademy.org/sicpjs/}{\color{DarkBlue}\emph{Structure and Interpretation 3 | of Computer Programs}, JavaScript Adaptation}. 4 | Source is a sublanguage of 5 | \href{http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf}{\color{DarkBlue} 6 | ECMAScript 2018 ($9^{\textrm{th}}$ Edition)} 7 | and defined in the documents titled ``Source \S $x$'', where $x$ refers to the 8 | respective textbook chapter. 9 | -------------------------------------------------------------------------------- /docs/specs/source_python_return.tex: -------------------------------------------------------------------------------- 1 | \subsection*{Restrictions} 2 | 3 | \begin{itemize} 4 | \item 5 | Single assignment language: Each variable 6 | can be assigned a value only once during its 7 | lifetime. 8 | 9 | \item 10 | Operators do not implicitly cast boolean 11 | values to integers. Booleans cannot be used 12 | interchangeably with integers in operations. 13 | 14 | \item 15 | Scope restriction: Each variable 16 | can only be accessed in the block it is 17 | declared. 18 | \end{itemize} 19 | 20 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection2/17.js: -------------------------------------------------------------------------------- 1 | function number_equal(exp, num) { 2 | return is_number(exp) && exp === num; 3 | } 4 | function make_product(m1, m2) { 5 | return number_equal(m1, 0) || number_equal(m2, 0) 6 | ? 0 7 | : number_equal(m1, 1) 8 | ? m2 9 | : number_equal(m2, 1) 10 | ? m1 11 | : is_number(m1) && is_number(m2) 12 | ? m1 * m2 13 | : list("*", m1, m2); 14 | } 15 | 16 | make_product(2, 3); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/9.js: -------------------------------------------------------------------------------- 1 | function make_perform(inst, machine, labels, operations, pc) { 2 | const action = perform_action(inst); 3 | 4 | if (is_operation_exp(action)) { 5 | const action_fun = make_operation_exp(action, machine, labels, operations); 6 | return () => { action_fun(); advance_pc(pc); } 7 | 8 | } else { 9 | error(inst, "Bad PERFORM instruction: ASSEMBLE"); 10 | } 11 | } 12 | 13 | function perform_action(inst) { 14 | return tail(inst); 15 | } -------------------------------------------------------------------------------- /docs/md/README_LISTS.md: -------------------------------------------------------------------------------- 1 | The functions in LISTS provide useful functions for list processing, 2 | as introduced on 3 | section 4 | 2.2 Hierarchical Data and the Closure Property 5 | of the textbook 6 | Structure and Interpretation 7 | of Computer Programs, JavaScript Adaptation (SICP JS). 8 | 9 | On the right, you see all predeclared LISTS functions, 10 | in alphabetical 11 | order. Click on a name to see how it is defined and used. 12 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection4/13.js: -------------------------------------------------------------------------------- 1 | function square_of_four(tl, tr, bl, br) { 2 | return painter => stack(beside(tl(painter), tr(painter)), 3 | beside(bl(painter), br(painter))); 4 | } 5 | function identity(x) { 6 | return x; 7 | } 8 | function flipped_pairs(painter) { 9 | const combine4 = square_of_four(turn_upside_down, flip_vert, 10 | flip_horiz, identity); 11 | return combine4(painter); 12 | } 13 | 14 | show(flipped_pairs(heart)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/11.js: -------------------------------------------------------------------------------- 1 | w2(70); // output: 30 2 | w1(50); // output: 50 3 | const w1 = make_withdraw_with_balance(100); 4 | const w2 = make_withdraw_with_balance(100); 5 | function make_withdraw_with_balance(balance) { 6 | return amount => { 7 | if (balance >= amount) { 8 | balance = balance - amount; 9 | return balance; 10 | } else { 11 | return "insufficient funds"; 12 | } 13 | }; 14 | } 15 | w2(40); // output: "Insufficient funds" -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/2.js: -------------------------------------------------------------------------------- 1 | function extract_labels(text, receive) { 2 | function helper(insts, labels) { 3 | const next_inst = head(text); 4 | 5 | return is_string(next_inst) 6 | ? receive(insts, pair(make_label_entry(next_inst, insts), labels)) 7 | : receive(pair(make_instruction(next_inst), insts), labels); 8 | } 9 | 10 | return text === undefined || is_null(text) 11 | ? receive(null, null) 12 | : extract_labels(tail(text), helper); 13 | } -------------------------------------------------------------------------------- /src/tracer/interface.ts: -------------------------------------------------------------------------------- 1 | import type { Node } from '../types' 2 | import type { StepperExpression, StepperPattern } from './nodes' 3 | 4 | export interface StepperBaseNode { 5 | type: Node['type'] 6 | isContractible(): boolean 7 | isOneStepPossible(): boolean 8 | contract(): StepperBaseNode 9 | oneStep(): StepperBaseNode 10 | substitute(id: StepperPattern, value: StepperExpression): StepperBaseNode 11 | freeNames(): string[] 12 | allNames(): string[] 13 | rename(before: string, after: string): StepperBaseNode 14 | } 15 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection3/7.js: -------------------------------------------------------------------------------- 1 | const tolerance = 0.00001; 2 | function fixed_point(f, first_guess) { 3 | function close_enough(x, y) { 4 | return abs(x - y) < tolerance; 5 | } 6 | function try_with(guess) { 7 | const next = f(guess); 8 | return close_enough(guess, next) 9 | ? next 10 | : try_with(next); 11 | } 12 | return try_with(first_guess); 13 | } 14 | function abs(x) { 15 | return x >= 0 ? x : -x; 16 | } 17 | fixed_point(math_cos, 1.0); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/35.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | // THIS IS NOT A CORRECT SOLUTION 5 | function square_list(items) { 6 | function iter(things, answer) { 7 | return is_null(things) 8 | ? answer 9 | : iter(tail(things), 10 | pair(answer, 11 | square(head(things)))); 12 | } 13 | return iter(items, null); 14 | } 15 | 16 | square_list(list(1, 2, 3, 4)); 17 | // returns: [1, [4, [9, [16, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection3/6.js: -------------------------------------------------------------------------------- 1 | function abs(x) { 2 | return x >= 0 ? x : -x; 3 | } 4 | const tolerance = 0.00001; 5 | function fixed_point(f, first_guess) { 6 | function close_enough(x, y) { 7 | return abs(x - y) < tolerance; 8 | } 9 | function try_with(guess) { 10 | const next = f(guess); 11 | return close_enough(guess, next) 12 | ? next 13 | : try_with(next); 14 | } 15 | return try_with(first_guess); 16 | } 17 | 18 | fixed_point(math_cos, 1.0); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/20.js: -------------------------------------------------------------------------------- 1 | // first_denomination, except_first_denomination 2 | // and no_more to be given by student 3 | function cc(amount, coin_values) { 4 | return amount === 0 5 | ? 1 6 | : amount < 0 || no_more(coin_values) 7 | ? 0 8 | : cc(amount, 9 | except_first_denomination(coin_values)) 10 | + 11 | cc(amount - first_denomination(coin_values), 12 | coin_values); 13 | } 14 | 15 | cc(100, us_coins); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection1/34.js: -------------------------------------------------------------------------------- 1 | function square(x) { 2 | return x * x; 3 | } 4 | // THIS IS NOT A CORRECT SOLUTION 5 | function square_list(items) { 6 | function iter(things, answer) { 7 | return is_null(things) 8 | ? answer 9 | : iter(tail(things), 10 | pair(square(head(things)), 11 | answer)); 12 | } 13 | return iter(items, null); 14 | } 15 | 16 | square_list(list(1, 2, 3, 4)); 17 | // returns: [1, [4, [9, [16, null]]]] -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section1/subsection1/12.js: -------------------------------------------------------------------------------- 1 | w2(40); // output: "Insufficient funds" 2 | w2(70); // output: 30 3 | w1(50); // output: 50 4 | const w1 = make_withdraw_with_balance(100); 5 | const w2 = make_withdraw_with_balance(100); 6 | function make_withdraw_with_balance(balance) { 7 | return amount => { 8 | if (balance >= amount) { 9 | balance = balance - amount; 10 | return balance; 11 | } else { 12 | return "insufficient funds"; 13 | } 14 | }; 15 | } 16 | w1(40); // output: 10 -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter3/section3/subsection1/6.js: -------------------------------------------------------------------------------- 1 | function append(x, y) { 2 | return is_null(x) 3 | ? y 4 | : pair(head(x), append(tail(x), y)); 5 | } 6 | function append_mutator(x, y) { 7 | set_tail(last_pair(x), y); 8 | } 9 | const x = list("a", "b"); 10 | const y = list("c", "d"); 11 | const z = append(x, y); 12 | display(z); // ["a", ["b", ["c", ["d", null]]]] 13 | display(tail(x)); // ??? 14 | const w = append_mutator(x, y); 15 | display(w); // ["a", ["b", ["c", ["d", null]]]] 16 | display(tail(x)); // ??? -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section5/subsection7/2.js: -------------------------------------------------------------------------------- 1 | "apply_dispatch", 2 | test(op("primitive_procedure"), reg("proc")), 3 | branch(label("primitive_apply")), 4 | test(op("compound_procedure"), reg("proc")), 5 | branch(label("compound_apply")), 6 | test(op("compiled_procedure"), reg("proc")), 7 | branch(label("compiled_apply")), 8 | go_to(label("unknown_procedure_type")), 9 | 10 | "compiled_apply", 11 | restore("continue"), 12 | assign("val", list(op("compiled_procedure_entry"), reg("proc"))), 13 | go_to(reg("val")), -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection1/12.js: -------------------------------------------------------------------------------- 1 | function eval_variable_declaration(stmt, env) { 2 | set_name_value(variable_declaration_name(stmt), 3 | evaluate(variable_declaration_value(stmt), env), 4 | env); 5 | } 6 | function eval_constant_declaration(stmt, env) { 7 | set_name_value(constant_declaration_name(stmt), 8 | evaluate(constant_declaration_value(stmt), env), 9 | env); 10 | } 11 | 12 | const my_program = parse("{ let x = 1; const y = 2; x + y; }"); 13 | evaluate(my_program, the_global_environment); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/11.js: -------------------------------------------------------------------------------- 1 | function is_register_exp(exp) { 2 | return is_tagged_list(exp, "reg"); 3 | } 4 | 5 | function register_exp_reg(exp) { 6 | return head(tail(exp)); 7 | } 8 | 9 | function is_constant_exp(exp) { 10 | return is_tagged_list(exp, "constant"); 11 | } 12 | 13 | function constant_exp_value(exp) { 14 | return head(tail(exp)); 15 | } 16 | 17 | function is_label_exp(exp) { 18 | return is_tagged_list(exp, "label"); 19 | } 20 | 21 | function label_exp_label(exp) { 22 | return head(tail(exp)); 23 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/1.js: -------------------------------------------------------------------------------- 1 | function good_enough(guess, x) { 2 | return abs(square(guess) - x) < 0.001; 3 | } 4 | function abs(x) { 5 | return x >= 0 ? x : -x; 6 | } 7 | function square(x) { 8 | return x * x; 9 | } 10 | function improve(guess, x) { 11 | return average(guess, x / guess); 12 | } 13 | function average(x,y) { 14 | return (x + y) / 2; 15 | } 16 | function sqrt_iter(guess, x) { 17 | return good_enough(guess, x) 18 | ? guess 19 | : sqrt_iter(improve(guess, x), x); 20 | } 21 | 22 | sqrt_iter(3,25); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection2/3.js: -------------------------------------------------------------------------------- 1 | function extract_labels(text, receive) { 2 | if (is_null(text)) { 3 | return pair(null, null); 4 | 5 | } else { 6 | const result = extract_labels(tail(text)); 7 | const insts = head(result); 8 | const labels = tail(result); 9 | const next_inst = head(text); 10 | 11 | return is_string(next_inst) 12 | ? pair(insts, pair(make_label_entry(next_inst, insts), labels)) 13 | : pair(pair(make_instruction(next_inst), insts), labels); 14 | } 15 | } -------------------------------------------------------------------------------- /src/tracer/nodes/Statement/index.ts: -------------------------------------------------------------------------------- 1 | import { StepperBlockStatement } from './BlockStatement' 2 | import { StepperExpressionStatement } from './ExpressionStatement' 3 | import { StepperFunctionDeclaration } from './FunctionDeclaration' 4 | import { StepperReturnStatement } from './ReturnStatement' 5 | import { StepperVariableDeclaration } from './VariableDeclaration' 6 | 7 | export type StepperStatement = 8 | | StepperExpressionStatement 9 | | StepperVariableDeclaration 10 | | StepperBlockStatement 11 | | StepperReturnStatement 12 | | StepperFunctionDeclaration 13 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section3/subsection3/8.js: -------------------------------------------------------------------------------- 1 | const tolerance = 0.00001; 2 | function fixed_point(f, first_guess) { 3 | function close_enough(x, y) { 4 | return abs(x - y) < tolerance; 5 | } 6 | function try_with(guess) { 7 | const next = f(guess); 8 | return close_enough(guess, next) 9 | ? next 10 | : try_with(next); 11 | } 12 | return try_with(first_guess); 13 | } 14 | function abs(x) { 15 | return x >= 0 ? x : -x; 16 | } 17 | fixed_point( 18 | y => math_sin(y) + math_cos(y), 19 | 1.0); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function gcd(a, b) { 2 | return b === 0 ? a : gcd(b, a % b); 3 | } 4 | function make_rat(n, d) { 5 | return pair(n, d); 6 | } 7 | function numer(x) { 8 | const g = gcd(head(x), tail(x)); 9 | return head(x) / g; 10 | } 11 | function denom(x) { 12 | const g = gcd(head(x), tail(x)); 13 | return tail(x) / g; 14 | } 15 | 16 | function print_rat(x) { 17 | display(numer(x)); 18 | display("-"); 19 | display(denom(x)); 20 | } 21 | 22 | const one_half = make_rat(1, 2); 23 | 24 | print_rat(one_half); -------------------------------------------------------------------------------- /docs/specs/source_2_stepper_style.tex: -------------------------------------------------------------------------------- 1 | % Some helper macros for writing the stepper specs in a more idiomatic way 2 | 3 | \newcommand{\gentzen}[2]{\[ 4 | \frac{ 5 | #1 6 | }{ 7 | #2 8 | } 9 | \]} 10 | 11 | % Entry header 12 | \newcommand{\sEntry}[2]{\paragraph{#1:} #2} 13 | 14 | % Template variables 15 | \newcommand{\sVar}[1]{\textnormal{\textit{#1}}} 16 | % Template fixed values ("keywords") 17 | \newcommand{\sKw}[1]{\textbf{\texttt{#1}}} 18 | % Quickahhh 19 | \newcommand{\sCode}[1]{\textbf{\texttt{#1}}} 20 | % \newcommand{\sGentzen}[2]{\gentzen{\sCode{#1}}{\sCode{#2}}} 21 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section2/subsection6/2.js: -------------------------------------------------------------------------------- 1 | function smallest_divisor(n) { 2 | return find_divisor(n, 2); 3 | } 4 | function find_divisor(n, test_divisor) { 5 | return square(test_divisor) > n 6 | ? n 7 | : divides(test_divisor, n) 8 | ? test_divisor 9 | : find_divisor(n, test_divisor + 1); 10 | } 11 | function divides(a, b) { 12 | return b % a === 0; 13 | } 14 | function square(x) { 15 | return x * x; 16 | } 17 | function is_prime(n) { 18 | return n === smallest_divisor(n); 19 | } 20 | 21 | is_prime(42); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section1/subsection4/4.js: -------------------------------------------------------------------------------- 1 | function make_interval(x, y) { 2 | return pair(x, y); 3 | } 4 | function lower_bound(i) { 5 | return head(i); 6 | } 7 | function upper_bound(i) { 8 | return tail(i); 9 | } 10 | function make_center_width(c, w) { 11 | return make_interval(c - w, c + w); 12 | } 13 | function center(i) { 14 | return (lower_bound(i) + upper_bound(i)) / 2; 15 | } 16 | function width(i) { 17 | return (upper_bound(i) - lower_bound(i)) / 2; 18 | } 19 | 20 | const my_interval = make_center_width(1, 0.5); 21 | width(my_interval); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection3/6.js: -------------------------------------------------------------------------------- 1 | function entry(tree) { 2 | return head(tree); 3 | } 4 | function left_branch(tree) { 5 | return head(tail(tree)); 6 | } 7 | function right_branch(tree) { 8 | return head(tail(tail(tree))); 9 | } 10 | function make_tree(entry,left,right) { 11 | return list(entry,left,right); 12 | } 13 | 14 | entry( 15 | left_branch( 16 | right_branch( 17 | make_tree(10, 18 | null, 19 | make_tree(30, 20 | make_tree(20,null,null), 21 | null))))); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection2/4.js: -------------------------------------------------------------------------------- 1 | function is_tagged_list(stmt, the_tag) { 2 | return is_pair(stmt) && head(stmt) === the_tag; 3 | } 4 | function is_assignment(stmt) { 5 | return is_tagged_list(stmt, "assignment"); 6 | } 7 | function assignment_name(stmt) { 8 | return head(tail(head(tail(stmt)))); 9 | } 10 | function assignment_value(stmt) { 11 | return head(tail(tail(stmt))); 12 | } 13 | 14 | const my_assignment_statement = parse("x = 1;"); 15 | display(assignment_name(my_assignment_statement)); 16 | display(assignment_value(my_assignment_statement)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection3/3.js: -------------------------------------------------------------------------------- 1 | function is_tagged_list(stmt, the_tag) { 2 | return is_pair(stmt) && head(stmt) === the_tag; 3 | } 4 | function make_return_value(content) { 5 | return list("return_value", content); 6 | } 7 | function is_return_value(value) { 8 | return is_tagged_list(value,"return_value"); 9 | } 10 | function return_value_content(value) { 11 | return head(tail(value)); 12 | } 13 | 14 | const my_return_value = make_return_value(42); 15 | display(is_return_value(my_return_value)); 16 | display(return_value_content(my_return_value)); -------------------------------------------------------------------------------- /src/utils/makeWrapper.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:ban-types 2 | export function makeWrapper(originalFunc: Function, wrappedFunc: Function) { 3 | for (const prop in originalFunc) { 4 | if (originalFunc.hasOwnProperty(prop)) { 5 | Object.defineProperty(wrappedFunc, prop, Object.getOwnPropertyDescriptor(originalFunc, prop)!) 6 | } 7 | } 8 | for (const prop of ['length', 'name']) { 9 | if (originalFunc.hasOwnProperty(prop)) { 10 | Object.defineProperty(wrappedFunc, prop, Object.getOwnPropertyDescriptor(originalFunc, prop)!) 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section2/subsection3/23.js: -------------------------------------------------------------------------------- 1 | function plus(x, y) { 2 | return x + y; 3 | } 4 | function times(x, y) { 5 | return x * y; 6 | } 7 | function accumulate_n(op, init, seqs) { 8 | return is_null(head(seqs)) 9 | ? null 10 | : pair(accumulate(op, init, map(x => head(x), seqs)), 11 | accumulate_n(op, init, map(x => tail(x), seqs))); 12 | } 13 | function dot_product(v, w) { 14 | return accumulate(plus, 0, 15 | accumulate_n(times, 1, list(v, w))); 16 | } 17 | 18 | dot_product(list(1, 2), list(3, 4)); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter1/section1/subsection7/13.js: -------------------------------------------------------------------------------- 1 | function conditional(predicate, then_clause, else_clause) { 2 | return predicate ? then_clause : else_clause; 3 | } 4 | function good_enough(guess, x) { 5 | return abs(square(guess) - x) < 0.001; 6 | } 7 | function improve(guess, x) { 8 | return average(guess, x / guess); 9 | } 10 | function sqrt_iter(guess, x) { 11 | return conditional(good_enough(guess, x), 12 | guess, 13 | sqrt_iter(improve(guess, x), 14 | x)); 15 | } 16 | 17 | sqrt_iter(3,25); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter4/section1/subsection3/10.js: -------------------------------------------------------------------------------- 1 | function set_name_value(name, val, env) { 2 | function scan(names, vals) { 3 | return is_null(names) 4 | ? error("internal error: name not found") 5 | : name === head(names) 6 | ? set_head(head(vals), val) 7 | : scan(tail(names), tail(vals)); 8 | } 9 | const frame = first_frame(env); 10 | return scan(frame_names(frame), 11 | frame_values(frame)); 12 | } 13 | 14 | const my_block = parse("{ let x = 1; x; }"); 15 | evaluate(my_block, the_global_environment); -------------------------------------------------------------------------------- /src/errors/base.ts: -------------------------------------------------------------------------------- 1 | import type { SourceLocation } from 'estree' 2 | 3 | export enum ErrorType { 4 | IMPORT = 'Import', 5 | RUNTIME = 'Runtime', 6 | SYNTAX = 'Syntax', 7 | TYPE = 'Type' 8 | } 9 | 10 | export enum ErrorSeverity { 11 | WARNING = 'Warning', 12 | ERROR = 'Error' 13 | } 14 | 15 | // any and all errors ultimately implement this interface. as such, changes to this will affect every type of error. 16 | export interface SourceError { 17 | type: ErrorType 18 | severity: ErrorSeverity 19 | location: SourceLocation 20 | explain(): string 21 | elaborate(): string 22 | } 23 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection3/9.js: -------------------------------------------------------------------------------- 1 | function entry(tree) { 2 | return head(tree); 3 | } 4 | function left_branch(tree) { 5 | return head(tail(tree)); 6 | } 7 | function right_branch(tree) { 8 | return head(tail(tail(tree))); 9 | } 10 | function make_tree(entry,left,right) { 11 | return list(entry,left,right); 12 | } 13 | function tree_to_list_1(tree) { 14 | return is_null(tree) 15 | ? null 16 | : append(tree_to_list_1(left_branch(tree)), 17 | pair(entry(tree), 18 | tree_to_list_1(right_branch(tree)))); 19 | } -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section4/subsection2/1.js: -------------------------------------------------------------------------------- 1 | function attach_tag(type_tag, contents) { 2 | return pair(type_tag, contents); 3 | } 4 | function type_tag(datum) { 5 | return is_pair(datum) 6 | ? head(datum) 7 | : Error("bad tagged datum in type_tag", datum); 8 | } 9 | function contents(datum) { 10 | return is_pair(datum) 11 | ? tail(datum) 12 | : Error("bad tagged datum in contents", datum); 13 | } 14 | 15 | const f_1 = list("A", 4); 16 | const my_frequency_1 = 17 | attach_tag("frequency_list", f_1); 18 | 19 | type_tag(my_frequency_1); -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter5/section2/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function make_assign(inst, machine, labels, operations, pc) { 2 | const target = get_register(machine, assign_reg_name(inst)); 3 | const value_exp = assign_value_exp(inst); 4 | const value_fun = is_operation_exp(value_exp) 5 | ? make_operation_exp(value_exp, machine, labels, operations) 6 | : make_primitive_exp(head(value_exp), machine, labels); 7 | 8 | function perform_make_assign() { 9 | set_contents(target, value_fun()); 10 | advance_pc(pc); 11 | } 12 | 13 | return perform_make_assign; 14 | } -------------------------------------------------------------------------------- /tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "noEmit": false, 6 | "skipLibCheck": true 7 | }, 8 | // Excludes are overwritten when using extends, so we 9 | // list all the excludes again 10 | "exclude": [ 11 | "src/stdlib/metacircular-interpreter", 12 | "src/stdlib/**/*.js", 13 | "node_modules", 14 | "dist", 15 | "sicp_publish", 16 | "src/**/__tests__/**", 17 | "src/**/__mocks__/**", 18 | "src/py-slang/src/tests", 19 | "src/utils/testing", 20 | "vitest.config.ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/__tests__/sicp/chapter2/section3/subsection3/2.js: -------------------------------------------------------------------------------- 1 | function is_element_of_set(x, set) { 2 | return ! is_null(set) && 3 | ( is_equal(x, head(set)) || 4 | is_element_of_set(x, tail(set)) ); 5 | } 6 | function is_equal(a, b) { 7 | return (is_pair(a) && is_pair(b) && 8 | is_equal(head(a), head(b)) && is_equal(tail(a), tail(b))) 9 | || 10 | a === b; 11 | } 12 | function adjoin_set(x, set) { 13 | return is_element_of_set(x, set) 14 | ? set 15 | : pair(x, set); 16 | } 17 | 18 | adjoin_set(10, adjoin_set(15, adjoin_set(20, null))); --------------------------------------------------------------------------------