├── .clang-format ├── .gitattributes ├── .github └── workflows │ └── c.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs ├── LICENSE ├── css3-github-buttons │ ├── LICENSE │ ├── gh-buttons.css │ └── gh-icons.png ├── documentation.html ├── download.html ├── examples.html ├── fonts │ ├── junction │ │ ├── junction-bold.eot │ │ ├── junction-bold.svg │ │ ├── junction-bold.ttf │ │ ├── junction-bold.woff │ │ ├── junction-light.eot │ │ ├── junction-light.svg │ │ ├── junction-light.ttf │ │ ├── junction-light.woff │ │ ├── junction-regular.eot │ │ ├── junction-regular.svg │ │ ├── junction-regular.ttf │ │ ├── junction-regular.woff │ │ └── junction.css │ └── league │ │ ├── .gitignore │ │ ├── leaguespartan-bold.eot │ │ ├── leaguespartan-bold.svg │ │ ├── leaguespartan-bold.ttf │ │ ├── leaguespartan-bold.woff │ │ ├── leaguespartan-bold.woff2 │ │ └── stylesheet.css ├── hljs-ms.js ├── hljs-railcasts.css ├── img │ ├── GitHub-Mark-32px.png │ ├── GitHub-Mark-Light-32px.png │ ├── heart.png │ ├── hello.png │ ├── logo.png │ ├── logosmall.png │ ├── mini.png │ ├── sub.png │ └── types.png ├── index.html ├── jquery-1.11.2.min.js ├── literature.html ├── local.css ├── old │ ├── binaries │ │ ├── microscheme_0.7_BUILD400_linux_32.tar.gz │ │ ├── microscheme_0.7_BUILD400_linux_64.tar.gz │ │ ├── microscheme_0.7_BUILD400_win_32.zip │ │ ├── microscheme_0.7_BUILD400_win_64.zip │ │ ├── microscheme_0.8_BUILD511_linux_32.tar.gz │ │ ├── microscheme_0.8_BUILD511_linux_64.tar.gz │ │ ├── microscheme_0.8_BUILD511_win_32.zip │ │ └── microscheme_0.8_BUILD511_win_64.zip │ ├── caveats.html │ ├── css │ │ ├── foundation.css │ │ ├── foundation.min.css │ │ └── normalize.css │ ├── download.html │ ├── examples.html │ ├── guide.html │ ├── guide2.html │ ├── guide3.html │ ├── guide4.html │ ├── guide5.html │ ├── guide6.html │ ├── guide7.html │ ├── help.html │ ├── img │ │ ├── .gitkeep │ │ └── hello.png │ ├── index.html │ ├── js │ │ ├── foundation.min.js │ │ ├── foundation │ │ │ ├── foundation.abide.js │ │ │ ├── foundation.accordion.js │ │ │ ├── foundation.alert.js │ │ │ ├── foundation.clearing.js │ │ │ ├── foundation.dropdown.js │ │ │ ├── foundation.interchange.js │ │ │ ├── foundation.joyride.js │ │ │ ├── foundation.js │ │ │ ├── foundation.magellan.js │ │ │ ├── foundation.offcanvas.js │ │ │ ├── foundation.orbit.js │ │ │ ├── foundation.reveal.js │ │ │ ├── foundation.tab.js │ │ │ ├── foundation.tooltip.js │ │ │ └── foundation.topbar.js │ │ ├── jquery.js │ │ ├── modernizr.js │ │ └── vendor │ │ │ ├── fastclick.js │ │ │ ├── jquery.cookie.js │ │ │ ├── jquery.js │ │ │ ├── modernizr.js │ │ │ └── placeholder.js │ ├── local.css │ ├── logo.png │ ├── logo.xcf │ ├── logosmall.png │ ├── logosquare.xcf │ ├── mini.png │ ├── sam.php │ └── workflow.html └── static │ └── dissertation.pdf ├── emulator.scm ├── examples ├── BLINK.ms ├── GERALD.ms ├── blink-led-morse.ms ├── clock.ms ├── fade.ms ├── helloworld.ms ├── marquee.ms ├── music.ms └── serial.ms ├── ffi_stuff ├── dump.py ├── ffi-test.ms ├── ffitest.c └── microscheme_types.c ├── libraries ├── ascii.ms ├── lcd.ms └── max7.ms ├── makefile └── src ├── assembly_hex.h ├── avr_core.ms ├── codegen.c ├── codegen.h ├── common.c ├── common.h ├── lexer.c ├── lexer.h ├── main.c ├── main.h ├── microscheme_hex.h ├── models.c ├── models.h ├── parser.c ├── parser.h ├── preamble.s ├── primitives.ms ├── scoper.c ├── scoper.h ├── stdlib.ms ├── treeshaker.c └── treeshaker.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | AllowShortCaseLabelsOnASingleLine: 'true' 4 | AllowShortFunctionsOnASingleLine: All 5 | AllowShortIfStatementsOnASingleLine: Always 6 | AllowShortLoopsOnASingleLine: 'true' 7 | AlwaysBreakBeforeMultilineStrings: 'true' 8 | BinPackArguments: 'false' 9 | BinPackParameters: 'false' 10 | BreakBeforeBraces: Allman 11 | BreakStringLiterals: 'false' 12 | ColumnLimit: '0' 13 | IncludeBlocks: Regroup 14 | IndentCaseLabels: 'true' 15 | IndentWidth: '4' 16 | 17 | ... 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ms linguist-language=Scheme 2 | -------------------------------------------------------------------------------- /.github/workflows/c.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | push: 5 | branches: [ '*' ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-20.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: get build dependencies 15 | run: | 16 | sudo apt update 17 | sudo apt -y install make avr-libc xxd cppcheck 18 | - name: static analysis 19 | run: make check 20 | - name: generate source 21 | run: make hexify 22 | - name: build 23 | run: make build 24 | - name: test 25 | run: ./microscheme examples/BLINK.ms 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | 5 | # Libraries 6 | *.lib 7 | *.a 8 | 9 | # Shared objects (inc. Windows DLLs) 10 | *.dll 11 | *.so 12 | *.so.* 13 | *.dylib 14 | 15 | # Executables 16 | *.exe 17 | *.out 18 | *.app 19 | 20 | src/*_hex.c 21 | bin/ 22 | release/ 23 | examples/*.s 24 | examples/*.elf 25 | examples/*.hex 26 | *.s 27 | *.elf 28 | *.hex 29 | 30 | working 31 | working/* 32 | 33 | production 34 | production/* 35 | 36 | microscheme 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ryan Suchocki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Microscheme 2 | =========== 3 | 4 | [![GitLab CI](https://gitlab.com/ryansuchocki/microscheme/badges/master/pipeline.svg)](https://gitlab.com/ryansuchocki/microscheme/-/commits/master) 5 | ![GitHub CI](https://github.com/ryansuchocki/microscheme/actions/workflows/c.yml/badge.svg) 6 | 7 | Microscheme is a Scheme subset designed for Atmel microcontrollers, especially as found on Arduino boards. 8 | 9 | Recent Changes 10 | -------------- 11 | 12 | 1. Microscheme now has apply! 13 | 2. Microscheme now has an FFI! 14 | 15 | Compiling 16 | --------- 17 | 18 | ### Quick-Start 19 | 20 | `$ make hexify` 21 | 22 | `$ make build` 23 | 24 | `$ ./microscheme examples/BLINK.ms` 25 | 26 | If you have an arduino *on hand*: 27 | 28 | `$ ./microscheme -m [MODEL] -d [/dev/WHATEVER] -auc examples/BLINK.ms` 29 | 30 | ### Detail 31 | 32 | The microscheme source code is located in src/, and includes files written in C (.c, .h), assembly (.s) 33 | and in microscheme (.ms). 34 | 35 | In order to compile microscheme, those source files written in assembly and microscheme are 'hexified', i.e. 36 | converted into C byte arrays by invoking `$ make hexify`. Next, the compiler is compiled by invoking `$ make build`. 37 | 38 | The result is a standalone binary called 'microscheme' which is entirely self-contained, and can be separated 39 | from other files in this repository. On linux systems, invoke `$ sudo make install` to copy the binary to 40 | /usr/local/bin/, thus making it available system-wide. 41 | 42 | Usage 43 | ----- 44 | 45 | As of the latest commit, the usage is: 46 | 47 | ``` 48 | Usage: microscheme [-auscvrio] [-m model] [-d device] [-p programmer] [-w filename] [-t rounds] program[.ms] 49 | 50 | Option flags: 51 | -a Assemble (implied by -u or -s) (requires -m) 52 | -u Upload (requires -d) 53 | -s Disassemble (to inspect final binary) 54 | -c Cleanup (removes intermediate files) 55 | -v Verbose 56 | -r Verify (Uploading takes longer) 57 | -i Allow the same file to be included more than once 58 | -o Disable optimisations 59 | -h Show this help message 60 | 61 | Configuration flags: 62 | -m model Specify a model (UNO/MEGA/LEO...) 63 | -d device Specify a physical device 64 | -p programmer Tell avrdude to use a particular programmer 65 | -w files 'Link' with external C or assembly files 66 | -t rounds Specify the maximum number of tree-shaker rounds 67 | 68 | ``` 69 | 70 | Prerequisites 71 | ------------- 72 | 73 | In order to compile microscheme, you will need some implementation of GCC and the unix utility XXD. (Readily 74 | available on Linux/OSX.) 75 | 76 | In order to assemble programs and upload them to real Arduinos, you will need some implementation of *avr-gcc*, *avr-libc* and *avrdude*. Microscheme will try to invoke these tools directly, if the -a or -u options are used. 77 | Packages are available on all good linux distro's: 78 | 79 | For example, on Arch linux: 80 | 81 | `$ sudo pacman -S avr-gcc avr-libc avrdude` 82 | 83 | Or, on Ubuntu or Debian: 84 | 85 | `$ sudo apt-get install gcc-avr avr-libc avrdude` 86 | 87 | These tools are available via the [Homebrew](http://brew.sh/) and [MacPorts](https://www.macports.org/) package 88 | managers on Mac OS X and the [winavr](http://winavr.sourceforge.net/) project on Windows. 89 | 90 | Targets 91 | ------- 92 | 93 | Microscheme currently supports the ATMega168/328 (used on the Arduino UNO), the ATMega2560 (used on most Arduino MEGA boards), and the ATMega32u4. The target controller is set using the command line argument `-m` follwed by `MEGA`, `UNO`, or `LEO` (not required if you're just compiling). 94 | 95 | Note: An Arduino Pro Mini with a 168/328 chip (programmed via an UNO board with its chip removed) can be treated as an UNO, because it uses the same chip. 96 | 97 | Other chips can be supported by writing model definitions in [models.c](src/models.c), containing values derived from the relevant Atmel datasheet. 98 | 99 | Compiler pipeline 100 | ----------------- 101 | 102 | The entire compiler pipeline, as orchestrated by main.c, is: 103 | 104 | > [source code] → lexer.c → [token tree] → parser.c → [abstract syntax tree] → scoper.c → [(scoped) AST] → treeshaker.c → [(reduced) AST] → codegen.c → [assembly code] ... 105 | 106 | If the -a (assemble) option is given: 107 | 108 | > [assembly code] → avr-gcc → [ELF binary] → avr-objcopy → [IHEX binary] ... 109 | 110 | If the -u (upload) option is given: 111 | 112 | > [IHEX binary] → avrdude → Arduino Device 113 | 114 | 115 | License 116 | ------- 117 | 118 | The MIT License (MIT) 119 | 120 | Copyright (c) 2014 Ryan Suchocki 121 | 122 | Permission is hereby granted, free of charge, to any person obtaining a copy 123 | of this software and associated documentation files (the "Software"), to deal 124 | in the Software without restriction, including without limitation the rights 125 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 126 | copies of the Software, and to permit persons to whom the Software is 127 | furnished to do so, subject to the following conditions: 128 | 129 | The above copyright notice and this permission notice shall be included in all 130 | copies or substantial portions of the Software. 131 | 132 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 133 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 134 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 135 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 136 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 137 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 138 | SOFTWARE. 139 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ryan Suchocki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/css3-github-buttons/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ryan Suchocki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/css3-github-buttons/gh-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/css3-github-buttons/gh-icons.png -------------------------------------------------------------------------------- /docs/download.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Microscheme 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 29 | 30 | 31 |
32 | 44 | 45 |
46 | 47 |

Downloading microscheme

48 |

A functional programming language for the Arduino

49 | 50 |

Pre-requisites

51 | 52 |

In order to assemble programs and upload them to real Arduinos, you will need some implementation of avr-gcc and avrdude. For most Linux distributions, these tools are available via the standard package managers. They are available via the Homebrew and MacPorts package managers for Mac OS X, and the winavr project on Windows.

53 | 54 |

Get the latest code

55 | 56 |

57 | The latest (not necessarily stable) code is always available via GitHub. 58 |

59 | 60 | 64 | 65 |

Stable Release (v0.9.3)

66 | 67 |

The latest stable release is available as source code, and as compiled binaries for Linux and Windows. This is the version of microscheme to which the online documentation applies.

68 | 69 |
70 | Source Code 71 |
72 | 73 |
74 | Linux 32-bit 75 | Linux 64-bit 76 |
77 | 78 | 82 | 83 |

Distribution Packages

84 | 85 |

Microscheme packages are available for the Pacman (Arch Linux) and Nix package managers.

86 | 87 |

License

88 |

The Microscheme source code and binaries are released under the MIT license.

89 | 90 |
91 |
92 | 93 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Microscheme 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 29 | 30 | 31 |
32 | 44 | 45 |
46 | 47 |

Examples

48 |

A functional programming language for the Arduino

49 | 50 |

GERALD

51 | 52 |

53 | GERALD—the fractal drawing robot—is a great example of why the functional programming paradigm is relevant to microcontroller platforms. The algorithm for tracing fractals (such as the Koch snowflake shown here) is intuitively expressed as a recursive procedure. GERALD is driven by stepper motors, which can be controlled accurately in software by sending sequences of high and low voltage signals to the microcontroller's General Purpose Input/Output pins. The low-level code to generate such sequences (which is essentially imperative) is also easily expressed in Scheme code, as sequences of side-effects are easily expressed as lists of (impure) procedures. For the full code, see 'examples/GERALD.ms' in the source code repository. 54 |

55 | 56 |
57 | 58 | 59 | 60 |

61 |   ;; Snippet from examples/GERALD.ms
62 | 
63 |   (define (segment level)
64 |     (if (zero? level)
65 |       (forward 3)
66 |       (begin
67 |         (segment (- level 1))
68 |         (left 60)
69 |         (segment (- level 1))
70 |         (right 120)
71 |         (segment (- level 1))
72 |         (left 60)
73 |         (segment (- level 1)))))
74 | 
75 |   (define (snowflake level)
76 |     (segment level)
77 |     (right 120)
78 |     (segment level)
79 |     (right 120)
80 |     (segment level)
81 |     (right 120))
82 | 
83 |   (snowflake 2)
84 | 
85 | 
86 |
87 | 88 |
89 |
90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/fonts/junction/junction-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-bold.eot -------------------------------------------------------------------------------- /docs/fonts/junction/junction-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-bold.ttf -------------------------------------------------------------------------------- /docs/fonts/junction/junction-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-bold.woff -------------------------------------------------------------------------------- /docs/fonts/junction/junction-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-light.eot -------------------------------------------------------------------------------- /docs/fonts/junction/junction-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-light.ttf -------------------------------------------------------------------------------- /docs/fonts/junction/junction-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-light.woff -------------------------------------------------------------------------------- /docs/fonts/junction/junction-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-regular.eot -------------------------------------------------------------------------------- /docs/fonts/junction/junction-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-regular.ttf -------------------------------------------------------------------------------- /docs/fonts/junction/junction-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/junction/junction-regular.woff -------------------------------------------------------------------------------- /docs/fonts/junction/junction.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face { 3 | font-family: 'Junction'; 4 | src: url('junction-light.eot'); 5 | src: url('junction-light.eot?#iefix') format('embedded-opentype'), 6 | url('junction-light.woff') format('woff'), 7 | url('junction-light.ttf') format('truetype'), 8 | url('junction-light.svg#junctionlight') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /docs/fonts/league/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/league/.gitignore -------------------------------------------------------------------------------- /docs/fonts/league/leaguespartan-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/league/leaguespartan-bold.eot -------------------------------------------------------------------------------- /docs/fonts/league/leaguespartan-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/league/leaguespartan-bold.ttf -------------------------------------------------------------------------------- /docs/fonts/league/leaguespartan-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/league/leaguespartan-bold.woff -------------------------------------------------------------------------------- /docs/fonts/league/leaguespartan-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/fonts/league/leaguespartan-bold.woff2 -------------------------------------------------------------------------------- /docs/fonts/league/stylesheet.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'League Spartan'; 3 | src: url('leaguespartan-bold.eot'); 4 | src: url('leaguespartan-bold.eot?#iefix') format('embedded-opentype'), 5 | url('leaguespartan-bold.woff2') format('woff2'), 6 | url('leaguespartan-bold.woff') format('woff'), 7 | url('leaguespartan-bold.ttf') format('truetype'), 8 | url('leaguespartan-bold.svg#league_spartanbold') format('svg'); 9 | font-weight: bold; 10 | font-style: normal; 11 | 12 | } -------------------------------------------------------------------------------- /docs/hljs-railcasts.css: -------------------------------------------------------------------------------- 1 | /* 2 | Five-color theme from a single blue hue. 3 | */ 4 | .hljs { 5 | display: block; 6 | overflow-x: auto; 7 | padding: 0.5em; 8 | background: #eaeef3; 9 | -webkit-text-size-adjust: none; 10 | } 11 | 12 | .hljs, 13 | .hljs-list .hljs-built_in { 14 | color: #00193a; 15 | } 16 | 17 | .hljs-keyword, 18 | .hljs-title, 19 | .hljs-important, 20 | .hljs-request, 21 | .hljs-header, 22 | .hljs-javadoctag { 23 | font-weight: bold; 24 | } 25 | 26 | .hljs-comment, 27 | .hljs-chunk { 28 | color: #738191; 29 | } 30 | 31 | .hljs-string, 32 | .hljs-title, 33 | .hljs-parent, 34 | .hljs-built_in, 35 | .hljs-literal, 36 | .hljs-filename, 37 | .hljs-value, 38 | .hljs-addition, 39 | .hljs-tag, 40 | .hljs-argument, 41 | .hljs-link_label, 42 | .hljs-blockquote, 43 | .hljs-header { 44 | color: #0048ab; 45 | } 46 | 47 | .hljs-decorator, 48 | .hljs-prompt, 49 | .hljs-yardoctag, 50 | .hljs-subst, 51 | .hljs-symbol, 52 | .hljs-doctype, 53 | .hljs-regexp, 54 | .hljs-preprocessor, 55 | .hljs-pragma, 56 | .hljs-pi, 57 | .hljs-attribute, 58 | .hljs-attr_selector, 59 | .hljs-javadoc, 60 | .hljs-xmlDocTag, 61 | .hljs-deletion, 62 | .hljs-shebang, 63 | .hljs-string .hljs-variable, 64 | .hljs-link_url, 65 | .hljs-bullet, 66 | .hljs-sqbracket, 67 | .hljs-phony { 68 | color: #4c81c9; 69 | } -------------------------------------------------------------------------------- /docs/img/GitHub-Mark-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/GitHub-Mark-32px.png -------------------------------------------------------------------------------- /docs/img/GitHub-Mark-Light-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/GitHub-Mark-Light-32px.png -------------------------------------------------------------------------------- /docs/img/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/heart.png -------------------------------------------------------------------------------- /docs/img/hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/hello.png -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/logo.png -------------------------------------------------------------------------------- /docs/img/logosmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/logosmall.png -------------------------------------------------------------------------------- /docs/img/mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/mini.png -------------------------------------------------------------------------------- /docs/img/sub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/sub.png -------------------------------------------------------------------------------- /docs/img/types.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/img/types.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Microscheme 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 29 | 30 | 31 |
32 | 44 | 45 |
46 | 47 |

microscheme.org

48 |

A functional programming language for the Arduino

49 | 50 |
51 |
52 | 53 |
54 |
55 |

56 |   ;; Hello World in Microscheme!
57 | 
58 |   (include "libraries/lcd.ms")
59 |   (lcd-init)
60 | 
61 |   (define foo "Hi, ")
62 |   (define bar "from Scheme!")
63 | 
64 |   (for-each-vector write (vector-concat foo bar))
65 |   
66 | 
67 |
68 |
69 | 70 |

71 | Microscheme, or (ms) for short, is a functional programming language for the Arduino, and for Atmel 8-bit AVR microcontrollers in general. Microscheme is a subset of Scheme, in the sense that every valid (ms) program is also a valid Scheme program (with the exception of Arduino hardware-specific primitives). The (ms) compiler performs function inlining, and features an aggressive tree-shaker, eliminating unused top-level definitions. Microscheme has a robust FFI (Foreign Function Interface) meaning that C code may be invoked directly from (ms) programs. Therefore, the power of the existing wealth of Arduino libraries is available within Microscheme. 72 |

73 |
74 |
75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/literature.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Microscheme 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 29 | 30 | 31 |
32 | 44 | 45 |
46 | 47 |

Microscheme Literature

48 |

A functional programming language for the Arduino

49 | 50 |

51 | Microscheme was originally a final-year undergraduate project, and had to be closed-source for examination purposes. The project has changed since then, and there have been rapid improvements since it was made open-source. However, much of the information in the original dissertation is still relevant. 52 |

53 | 54 |

55 | More recently, a short paper was prepared for the Scheme and Functional Programming workshop, containing a concise exposition of the Microscheme runtime system, and some of the considerations necessary for very resource-constrained platforms such as the ATMega controllers. This paper was very kindly presented by Will Byrd. 56 |

57 | 58 |
59 | 60 |

61 | Original Dissertation
62 | An extensive account of the project motivations and development.
63 | Download (PDF) From June 2014 64 |

65 | 66 |
67 | 68 |

69 | SFP ‘14 Paper
70 | A condensed technical exposition of the project.
71 | SFP 2014 72 | Download (PDF) From October 2014 73 |

74 | 75 |
76 | 77 |
78 |
79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/local.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 980px; 3 | margin: 40px auto; 4 | padding: 0px 20px; 5 | overflow: hidden; 6 | } 7 | 8 | .container .nav { 9 | width: 150px; 10 | float: left; 11 | } 12 | 13 | .container .content { 14 | width: 800px; 15 | float: left; 16 | margin-left: 30px; 17 | overflow: hidden; 18 | } 19 | 20 | .side-nav { 21 | display: block; 22 | margin: 0; 23 | padding: 0.875rem 0; 24 | list-style-type: none; 25 | list-style-position: inside; 26 | font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; 27 | } 28 | 29 | .side-nav li { 30 | font-size: 0.875rem; 31 | border-bottom: 1px solid #e6e6e6; 32 | } 33 | 34 | .side-nav li a { 35 | padding: 10px 0px; 36 | } 37 | 38 | .side-nav li.last { 39 | color: #BBB; 40 | font-size: 0.7em; 41 | text-align: center; 42 | border-bottom: none; 43 | margin-top: 10px; 44 | } 45 | 46 | .side-nav li .small-logo { 47 | width: 16px; 48 | height: 16px; 49 | margin-top: 2px; 50 | margin-right: 10px; 51 | float:right; 52 | opacity: 0.3; 53 | } 54 | 55 | .side-nav li:hover .small-logo { 56 | opacity: 0.4; 57 | } 58 | 59 | .side-nav li a:link, .side-nav li a:visited { 60 | display: block; 61 | color: #008cba; 62 | text-decoration: none; 63 | } 64 | 65 | .side-nav li a:hover { 66 | display: block; 67 | color: #003c6a; 68 | text-decoration: none; 69 | } 70 | 71 | .side-nav li.active a { 72 | display: block; 73 | color: #4d4d4d; 74 | } 75 | 76 | * { 77 | font-family: 'Open Sans', sans; 78 | } 79 | 80 | h1 { 81 | font-family: 'Open Sans', sans; 82 | font-weight: 100; 83 | 84 | 85 | font-size: 37px; 86 | 87 | color: #222; 88 | 89 | margin-top: 10px; 90 | margin-bottom: 0px; 91 | } 92 | 93 | h2 { 94 | font-family: 'Open Sans', sans; 95 | font-weight: 100; 96 | font-size: 23px; 97 | color: #6f6f6f; 98 | 99 | margin-top: 3px; 100 | 101 | margin-bottom: 25px; 102 | } 103 | 104 | h3 { 105 | font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; 106 | font-weight: 100; 107 | font-size: 19px; 108 | color: #222; 109 | 110 | margin-top: 20px; 111 | margin-bottom: 0px; 112 | } 113 | 114 | p, td, th { 115 | font-family: 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; 116 | font-weight: normal; 117 | font-size: 16px; 118 | line-height: 26px; 119 | color: #222; 120 | } 121 | 122 | code, code span { 123 | font-family: monospace; 124 | font-size: 12px; 125 | } 126 | 127 | code { 128 | padding: 20px !important; 129 | } 130 | 131 | a:link, a:visited { 132 | color: #003c6a; 133 | text-decoration: none; 134 | } 135 | 136 | a:hover, a:active { 137 | color: #003c6a; 138 | text-decoration: underline; 139 | } 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | .msinfo { 153 | margin-left: 10px; 154 | line-height: 20px; 155 | margin-bottom: 0px; 156 | margin-top: 0px; 157 | 158 | padding: 3px; 159 | 160 | border: 1px solid #FFFFFF; 161 | 162 | font-size: 14px; 163 | 164 | /*background-color: #F5F5FF; 165 | border: 1px solid #F0F0FF; 166 | border-radius: 6px;*/ 167 | } 168 | 169 | .msinfo:hover { 170 | /*background-color: #EEEEFF; 171 | border: 1px solid #CCCCDD; 172 | border-radius: 6px;*/ 173 | } 174 | 175 | .msform { 176 | padding: 1px 6px; 177 | border-radius: 6px; 178 | 179 | font-family: monospace; 180 | font-size: 13px; 181 | 182 | white-space: pre; 183 | 184 | background-color: #dadef3; 185 | color: #00092a; 186 | } 187 | 188 | .msform:hover { 189 | background-color: #cacee3; 190 | } 191 | 192 | .msform strong { 193 | font-family: monospace; 194 | font-size: 13px; 195 | } 196 | 197 | .msform em { 198 | opacity: 0.8; 199 | font-family: monospace; 200 | font-size: 13px; 201 | } 202 | 203 | il { 204 | font-family: monospace; 205 | font-size: 13px; 206 | color: #000065 207 | } 208 | 209 | 210 | 211 | 212 | 213 | 214 | .row { 215 | clear: both; 216 | } 217 | 218 | .lefthalf { 219 | float: left; 220 | width: 48%; 221 | 222 | } 223 | 224 | .righthalf { 225 | width: 48%; 226 | float: right; 227 | 228 | } 229 | 230 | .newrow { 231 | width: 100%; 232 | float: left; 233 | clear: both; 234 | } 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | table { 244 | border-collapse: collapse; 245 | margin: 30px auto; 246 | } 247 | 248 | td, th { 249 | border: 1px solid #191919; 250 | padding: 5px 16px; 251 | 252 | } 253 | 254 | th { 255 | font-weight: 600; 256 | } 257 | 258 | 259 | 260 | 261 | 262 | 263 | hr { 264 | height: 0px; 265 | border: none; 266 | border-bottom: 1px solid #e2e2e2; 267 | margin-top: 20px; 268 | margin-bottom: 0px; 269 | } 270 | -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.7_BUILD400_linux_32.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.7_BUILD400_linux_32.tar.gz -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.7_BUILD400_linux_64.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.7_BUILD400_linux_64.tar.gz -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.7_BUILD400_win_32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.7_BUILD400_win_32.zip -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.7_BUILD400_win_64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.7_BUILD400_win_64.zip -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.8_BUILD511_linux_32.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.8_BUILD511_linux_32.tar.gz -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.8_BUILD511_linux_64.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.8_BUILD511_linux_64.tar.gz -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.8_BUILD511_win_32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.8_BUILD511_win_32.zip -------------------------------------------------------------------------------- /docs/old/binaries/microscheme_0.8_BUILD511_win_64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/binaries/microscheme_0.8_BUILD511_win_64.zip -------------------------------------------------------------------------------- /docs/old/caveats.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Caveats

23 |

The current state of the project

24 | 25 |

The compiler is being released now because it is at a stage where substantial, useful programs can be compiled. It is still, however, a work-in-progress: and that's why the current version is 0.6. The key deficiencies, that are stopping it from being version 1.0, are explained here.

26 | 27 |
  • Garbage Collection: is not currently implemented. Garbage collection is an important feature because several primitive procedures silently use memory without warning, which is never given back. For example, calling ‘(reverse …)’ on a list creates a new, reversed list in memory. If you call such procedures enough, the Arduino will eventually run out of RAM and start behaving unpredictably.
  • 28 | 29 |
    30 | 31 |
  • The numeric stack is fairly limited. There are no signed numbers, and no floating-point support. On the other hand, the long.ms and fixedpoint libraries have shown how richer numeric types can easily be built using pairs and numbers.
  • 32 | 33 |
    34 | 35 |
  • Arduino Input/Output functionalities are not complete. There is full support for digital I/O and sending of serial data. However, receiving of serial data is not complete. Input and output via the analog pins is not supported yet.
  • 36 | 37 |
    38 | 39 |
  • The compiled programs are large and slow. The number of instructions generated for a given microscheme program is ~10 times more than an equivalent C program. (This is not surprising because the GCC compiler has been around for a long time, and has had millions of man-hours spent on its optimisations.) However, the increased number of instructions is the price paid for the massively richer runtime semmantics of a dynamically typed, functional language like Scheme. Also, the arduino has plenty (~128K) of ROM, and I have not yet seen a microscheme program that even half fills it.

    Microscheme will probably never beat GCC on performance, but the main motivation for it is to give people the choice of using the functional style on the Arduino.

  • 40 | 41 |
42 | 43 |
44 |
45 |
46 | 47 |
48 | 68 |
69 |
70 |
71 | 72 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/old/download.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | microscheme.org 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |
21 |
22 |
23 |

Getting Started

24 |

Downloading microscheme and its pre-requisites…

25 | 26 |
Microscheme Compiler
27 |

The microscheme compiler is written in pure C (99), and relies only on standard C libraries. Linux and MS Windows binaries are provided. The current release is v0.8, build 511

28 |
Update Alert Version 0.8 now available, featuring arbitrary lambda nesting and multiple-include protection.
29 | 30 |
31 |
32 |
33 |
Linux Binaries
34 |

A .tar.gz archive containing the compiler, libraries, example program, and a makefile for automating the build process

35 |

32-bit Linux 36 | 64-bit Linux

37 |
38 |
39 | 40 |
41 |
42 |
Windows Binaries
43 |

A ZIP archive containing the compiler, libraries and example program.

44 |

32-bit Windows 45 | 64-bit Windows

46 |
47 |
48 | 49 | 50 |
51 | 52 | 53 |
54 | 55 |
License
56 |

The standalone binaries provided here are released under the (CC BY-NC-ND 4.0) license 57 | Creative Commons Licence. 58 |

59 | 60 |
61 |
Changelog
62 |
    63 |
  • Version 0.8, Build 511: Arbitrary lambda nesting (fixed closures). Multiple-include protection.
  • 64 |
  • Version 0.7, Build 400: Full any-dimensional vector support. Minor bug-fixes.
  • 65 |
  • Version 0.7, Build 363: Improved performance, full arduino UNO support
  • 66 |
  • Version 0.6: Initial release. Full arduino MEGA support.
  • 67 |
68 | 69 |
70 | 71 |
Source
72 |

Since this compiler is my final-year (dissertation) project, the code will not be available until it is submitted and marked

73 | 74 |
75 | 76 |
Required tools
77 |

Microscheme compiles your programs, but it does not assemble, link, or upload them. These functions are provided by avr-gcc and avrdude, which are available in mainstream Linux repositories. For example:

78 |

On Arch Linux, run: 79 |

    $ sudo pacman -S avr-gcc
 80 |     $ sudo pacman -S avrdude

81 | 82 |

On Ubuntu, run: 83 | 84 |

    $ sudo apt-get install gcc-avr
 85 |     $ sudo apt-get install avrdude

86 |

The winavr project provides a port of both these tools for MS Windows.

87 | 88 | 89 | 90 |
91 | 92 |
93 | 94 |
95 | 96 |
97 | 116 |
117 |
118 |
119 | 120 | 121 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /docs/old/examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Examples

23 | 24 |
Hello, world!
25 |

Firstly, the canonical ‘Hello World’ example: (If you would like to see the output, it might be a good idea to have a 16×2 LCD shield such as this is connected.)

26 | 27 |
(include "libraries/list.ms")
 28 | (include "libraries/io.ms")
 29 | (include "libraries/lcd.ms")
 30 | 
 31 | (lcd_init)
 32 | 
 33 | (for-each-vector print "Hello, World!")
34 | 35 |
Interacting with the world
36 |

Using the general purpose digital input/output pins on the arduino is simple. Assuming you are using an Arduino MEGA, and have an LED connected to digital pin 20, you can make it blink like so:

37 | 38 |
(include "libraries/io.ms")
 39 | 
 40 | (set-ddr 20 #t)         ; Set direction register for pin 20 to 'output'
 41 | 
 42 | (define (blink_forever)
 43 |   (set-pin 20 #t)       ; Set pin 20 high
 44 |   (pause 500)           ; Wait half a second
 45 |   (set-pin 20 #f)       ; Set pin 20 low
 46 |   (pause 500)           ; Wait half a second
 47 |   (blink_forever))      ; Repeat...
 48 | 
 49 | (blink_forever)
50 | 51 |
Fibonacci Sequence
52 |

In the next example, we build a list of numbers from the Fibnacci sequence. This time, rather than producing output on an LCD screen, we send each of the values to some external device via the serial interface.

53 | 54 |
(include "libraries/list.ms")
 55 | 
 56 | (define (fibstep i acc n2 n1)
 57 |   (if (= 0 i)
 58 |     acc
 59 |     (fibstep (- i 1) (cons (+ n2 n1) acc) n1 (+ n2 n1))))
 60 | 
 61 | (define (fib n)
 62 |     (reverse (fibstep n () 0 1)))
 63 | 
 64 | (for-each serial-send (fib 10))
65 | 66 |
Factorial
67 |

Here we see two approaches to writing a factorial function; the second of which is tail-recursive. In each function, the value of (stacksize), which returns the number of bytes occupied at the moment of evaluation, is reported at the deepest part of the recursion. This demonstrates the importance of the tail-recursive style in environments such as microcontrollers.

68 | 69 |
(include "libraries/list.ms")
 70 | 
 71 | (define (factorial n)
 72 |   (if (zero? n)
 73 |     (begin (serial-send (stacksize)) 1)
 74 |     (* (factorial (- n 1)) n)))
 75 | 
 76 | (serial-send (factorial 7))
 77 | 
 78 | (define (tail-factorial n acc)
 79 |   (if (zero? n)
 80 |     (begin (serial-send (stacksize)) acc)
 81 |     (tail-factorial (- n 1) (* acc n))))
 82 | 
 83 | (serial-send (tail-factorial 7 1))
84 | 85 | 86 | 87 | 88 | 89 |
90 |
91 |
92 | 93 |
94 | 113 |
114 |
115 |
116 | 117 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /docs/old/guide2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Language Guide: Page 2

23 |

A crash course in the particular workings of microscheme

24 | 25 | 26 | 27 |
Fundemental Forms (continued)
28 | 29 | 30 |
  • 31 |

    Assignment: (set! <name> <expr>)

    32 |

    Assignment looks just like definition, but with the ‘set!’ keyword instead of ‘define’. This is used to change the value to which some variable name is bound. That could be a global variable, which is introduced by (define …), a procedure argument, or a local variable introduced by (let …) The set keyword includes an exclamation mark to remind you that it is changing the state of the system; and this is why Scheme is considered not to be purely functional.

  • 33 | 34 |
  • 35 |

    Conditional: (<predicate> <consequent> <alternative>)

    36 |

    The conditional form takes at least a predicate and a consequent, and optinally an alternative. Each of these are expressions of any kind. If the predicate evaluates to true (In Scheme, anything other than false, denoted #f, counts as true) then the consequent will be evaluated. If the predicate evaluates to false, and an alternative is given, then it will be evaluated. This is subtly different from the conditional branches of imperative programming. As well as making a decision about which expression to evaluate, the conditional itself inherits the value of whichever branch is chosen. This means you can use the whole expression as a subexpression, whose value depends on the predicate. e.g. (+ 1 (if (= 2 3) 7 13)) evaluates to 14.

  • 37 | 38 |
  • 39 |

    Conjunction: (and A B C …)

    40 |

    The conjunction form takes any number of arguments, each of which is a subexpression. It will evaluate those expressions in order. If it reaches one that evaluates to false (denoted #f), then it will stop and return #f. If none of them evaluates to #f, then the value of the final expression will be returned (remember, anything other than #f is considered true). Using this form with zero arguments is equivalent to the true constant #t.

    41 |
  • 42 | 43 |
  • 44 |

    Disjunction: (or A B C …) 45 |

    Like conjunction, this disjunction form evaluates each of its arguments in order. If any one of them evaluates to anything other than #f, it stops and returns that value. If it reaches the end of the list, and every expression evaluated to #f, then it returns #f. Using this form with zer oarguments is equivalent to the false constant #f.

    46 | 47 |

    When used with Boolean type values, the conjunctive and disjunctive forms work just like boolean operators in imperative languages. (or #f #t #f) evaluates to #t and so forth. In Scheme, however, these forms perform a much more powerful function. Since they are variadic, and will keep evaluating until a false or true subexpression is reached respectively, they can be used as control-flow mechanisms in place of nested (if …) forms.

    48 | 49 |
  • 50 | 51 |
  • 52 |

    53 | Local Binding: (let ((a X) (b Y) (c Z) …) B …)

    54 | 55 |

    The let form is used to bind names to values only for a specific part of the program. The first argument to let is a list of binding pairs. Each binding pair is a pair of brackets containing a variable name and an expression. The expressions that are given as the body ‘B …’ are evaluated with those names bound to their corrseponding values, and the value of the final expression is returned. Those bindings do not persist outside of the let form. For any code outside of the let's parentheses, the variables a b c … are unchanged, and may not be defined at all.

    56 | 57 |

    Important nuances:

    1. Even if you only give one binding pair, the parentheses around the list of binding pairs is still needed. Hence, you end up with double brackets: (let ((x 5)) (+ x 1)). Missing those is a common mistake.
    2. The variable bindings apply in the body, but not within other binding pairs in the list. i.e., the expression Y should not rely on X being bound to a.

  • 58 | 59 |
  • 60 |

    61 | Sequence: (begin B1 B2 …)

    62 |

    Finally, you can group together expressions with the sequencial form, using the begin keyword. The whole thing is treated as one expression, whose subexpressions are executed in sequence. As usual, the value of the final subexpression is returned for the overall expression.

    63 | 64 |

    You can use this in cases where you want to guarantee a group of expressions will be evaluated, or where you want to give multiple expressions in a context where only one is expected.

    65 | 66 |

    (+ 1 (begin 2 4 6)) evaluates to 7. The subexpressions 2 and 4 are evaluated, but they have no effect. 6 is evaluated and returned to the outer + procedure.

  • 67 |
68 | 69 |
70 | 71 |
    72 |
  • «
  • 73 |
  • 1
  • 74 |
  • 2
  • 75 |
  • 3
  • 76 |
  • 4
  • 77 |
  • 5
  • 78 |
  • 6
  • 79 |
  • 7
  • 80 |
  • »
  • 81 |
82 | 83 | 84 | 85 |
86 |
87 |
88 | 89 |
90 | 109 |
110 |
111 |
112 | 113 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /docs/old/guide3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Language Guide: Page 3

23 |

A crash course in the particular workings of microscheme

24 | 25 | 26 | 27 |
Primitive Procedures
28 | 29 |

Primitive procedures are procedures that are built-in to the language. This means that the compiler produces efficient low-level routines for them.

30 | 31 |

Unlike full-blown Scheme, microscheme primitives are not first-class. i.e., they can only appear in the function application form. This is a problem when you want to pass a primitive function as the argument to a higher-order function such as map. For example, you may want to invert a list of Booleans: (map not list_of_booleans).

32 | 33 |

The solution is to make a simple wrapper-function which is first-class but performs the same function as the primitive you want to work with: (define (not* x) (not x)).

34 | 35 |

Then, you are free to use it as a value: (map not* list_of_booleans). This might seem annoying, but it is not without good reason. Making all primitive functions first-class would tie up around .5 KB of RAM. On the arduino, RAM is precious. This compromise ammounts to you, the programmer, telling the compiler exactly which primitives need to be loaded into RAM. For the vast majority of programs, this ammounts to a massive memory saving.

36 | 37 |
Available Primitives
38 |

The primitive procedures built-in to compiler version 0.6 are:

39 |
    40 |
  • =, >, >=, <, <=, not
  • 41 |
  • +, -, *, div, mod, zero?
  • 42 |
  • number?, pair?, vector?, procedure?, char?, boolean?, null?
  • 43 |
  • cons, car, cdr, set-car!, set-cdr!
  • 44 |
  • list, vector
  • 45 |
  • vector-length, vector-ref, vector-set!
  • 46 |
  • assert, error
  • 47 |
  • include, stacksize, heapsize, pause
  • 48 |
  • serial-send, digital-state, set-digital-state
  • 49 |
50 | 51 |
52 | 53 |
    54 |
  • «
  • 55 |
  • 1
  • 56 |
  • 2
  • 57 |
  • 3
  • 58 |
  • 4
  • 59 |
  • 5
  • 60 |
  • 6
  • 61 |
  • 7
  • 62 |
  • »
  • 63 |
64 | 65 | 66 | 67 |
68 |
69 |
70 | 71 |
72 | 92 |
93 |
94 |
95 | 96 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/old/guide4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Language Guide: Page 4

23 |

A crash course in the particular workings of microscheme

24 | 25 | 26 | 27 |
Type System
28 | 29 |

Microscheme has a strong dynamic type system. It is strong in the sense that:

30 |
  • All values have a specific, definite type
  • 31 |
  • No type coersion occurs
  • 32 |
  • Procedures are generally valid for a specific set of types
  • 33 |
  • Type exceptions are raised when procedures are applied to values of the wrong type
34 |

It is dynamic in the sense that a variable is not restricted to hold values of a certain type. The type of value to which a variable name will be bound is not known until runtime, and can change as the program progresses.

35 | 36 |

The built-in types are: Number, Char, Boolean, Pair, Vector, ‘The Empty List’ aka null, which is said to have a type of its own, and Procedure. From these basic types we can infer compound types. A List is defined to be something of the type null or pair where the value of the cdr field has type List. This definition is effectively implemented by the (list? …) function in the ‘list.ms’ library.

37 | 38 |

Even though the built-in numeric type is fairly restricted (15-bit unsigned integer), a richer numeric stack can be built using combinations of pairs, vectors and numbers. For example, the 'xtypes.ms' library provides types long and fp, which represent 8-digit unsigned integers, and 4+4 digit fixed-point real numbers respectively.

39 | 40 |

For every type, there is a predicate function which answers the question 'is this value of type X'. These predicates are consistently formed by appending a question mark to the type name. For example, (number? 4) evaluates to #t. (boolean? 4) evaluates to #f. (boolean? (number? 4)) evaluates to #t.

41 | 42 |

Procedures for converting between types are formed with an arrow between the type names, e.g. (vector->list a b). These conversions are not provided for many types, but they can be written manually.

43 | 44 | 45 |
46 | 47 |
    48 |
  • «
  • 49 |
  • 1
  • 50 |
  • 2
  • 51 |
  • 3
  • 52 |
  • 4
  • 53 |
  • 5
  • 54 |
  • 6
  • 55 |
  • 7
  • 56 |
  • »
  • 57 |
58 | 59 | 60 | 61 |
62 |
63 |
64 | 65 |
66 | 86 |
87 |
88 |
89 | 90 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /docs/old/guide5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Language Guide: Page 5

23 |

A crash course in the particular workings of microscheme

24 | 25 | 26 |
Microscheme Libraries
27 |

Microscheme supports the (include …) primitive, which effectively loads the whole contents of another file into the program. This allows commonly used program segments to be saved in 'libraries' that can be included in any other program. Typically, libraries contain definitions, but do not perform any input or output, so including them simply makes a set of procedures and data structures available to the program. Some useful libraries are included with microscheme, and more will become available as the project matures:

28 | 29 |

libraries/io.ms provides digital Input/Output functionality. This allows you to work with the Arduino's digital I/O pins, using the indices given to them on the arduino board. It provides the procedures: 30 |

  • (set-ddr N X) to set the DDR (data-direction-register) for a pin. N is the pin number. X is #f for ‘input’ and #t for ‘output’.
  • 31 |
  • (get-ddr N) returns a boolean representing the DDR value for pin N. #t means ‘output’.
  • 32 |
  • (set-pin N Y) sets the value (high or low) for pin N.
  • 33 |
  • (set-pin N Y) gets the value (high or low) of pin N.
  • 34 |

35 | 36 |

libraries/list.ms provides various functions for working with lists, which are linear data structures built using pairs and null. Procedures provided include: 37 |

    38 |
  • (list? X) returns true if and only if X is a list.
  • 39 |
  • (reverse X) if X is a list, returns a new list which is the reverse of it.
  • 40 |
  • (map P X) returns a list formed by performing procedure P on every element of list X.
  • 41 |
  • foldr, foldl, for-each, all various common higher-order list procedures.
  • 42 |
  • (vector->list V) returns a list whose elements are identical to those of vector V.
  • 43 |
44 | 45 | NB: the primitive (list …) for building lists is built-in, and implemented efficiently by the compiler.

46 | 47 |

libraries/long.ms provides an implementation for 8-digit unsigned integers: 48 |

  • (long hi lo) forms a long where hi represents the high four digits and lo represents the low four digits of the number. The number 994020 is produced by (long 99 4020).
  • 49 |
  • (hi X) and (lo X) extract the high and low parts of a long.
  • 50 |
  • (long? X) returns true if X is a valid long. Warning: any pair of numbers will satisfy this.
  • 51 |
  • l+ l- l* l/ standard arithmetic operators. (NB: l* and l/ are slow, software-based implementations.
  • 52 |
  • l++ l-- l** are in-place versions of l+ l- and l*. i.e. (l++ lX lY) is equivalent to (set! lX (l+ lX lY)), but allocates no new memory. You should use these operators wherever possible
  • 53 |
  • l= l< l> l<= l>= standard numeric comparators.
  • 54 |
55 |

56 | 57 |

libraries/fixedpoint.ms provides an implementation for 5+5 digit unsigned fixed-point reals: 58 |

59 | 60 |

NB: including the xtypes library has the same effect as including long and fixedpoint individually, but saves memory by taking advantage of the overlap between their functions.

61 | 62 | 63 |
64 | 65 |
    66 |
  • «
  • 67 |
  • 1
  • 68 |
  • 2
  • 69 |
  • 3
  • 70 |
  • 4
  • 71 |
  • 5
  • 72 |
  • 6
  • 73 |
  • 7
  • 74 |
  • »
  • 75 |
76 | 77 | 78 | 79 |
80 |
81 |
82 | 83 |
84 | 104 |
105 |
106 |
107 | 108 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /docs/old/guide6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Language Guide: Page 6

23 |

A crash course in the particular workings of microscheme

24 | 25 |
Compiler Errors
26 | 27 |

As of version 0.6, build 230, the possible compile-time errors are:

28 | 29 |
 30 | 0  Out of memory
 31 | 1  Char buffer full
 32 | 2  while lexing the file '%s'. File could not be opened
 33 | 3  Comment before end of token
 34 | 4  Extraneous )
 35 | 5  Missing )
 36 | 6  Procedure '%s' is primitive, and cannot be used as a value
 37 | 7  Non-identifier in formal argument list
 38 | 8  Malford lambda. No formals given
 39 | 9  Wrong number of operands to IF form
 40 | 10 First operand to SET should be IDENTIFIER
 41 | 11 Wrong number of operands to SET form
 42 | 12 Wrong number of operands to DEFINE form
 43 | 13 Non-identifier in formal argument list
 44 | 14 First operand to DEFINE should be IDENTIFIER or PARENS
 45 | 15 Definition not allowed here
 46 | 16 Malformed Binding
 47 | 17 Malformed LET?
 48 | 18 First operand to INCLUDE should be STRING
 49 | 19 Wrong number of operands to INCLUDE form
 50 | 20 Unknown parenthesized form
 51 | 21 Unknown form\n
 52 | 22 Unexpected list of expressions
 53 | 23 NOT IN SCOPE %s
 54 | 24 Integer constant too large
 55 | 25 Freevar refs of degree > 1 not supported yet
 56 | 26 No primitive P taking N arguments
 57 | 27 Internal Error
 58 | 
59 | 60 |
61 | 62 |
    63 |
  • «
  • 64 |
  • 1
  • 65 |
  • 2
  • 66 |
  • 3
  • 67 |
  • 4
  • 68 |
  • 5
  • 69 |
  • 6
  • 70 |
  • 7
  • 71 |
  • »
  • 72 |
73 | 74 | 75 | 76 |
77 |
78 |
79 | 80 |
81 | 100 |
101 |
102 |
103 | 104 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /docs/old/guide7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Language Guide: Page 7

23 |

A crash course in the particular workings of microscheme

24 | 25 | 26 |
Runtime Exceptions
27 | 28 | 29 |

Like Scheme, microscheme is strongly, dynamically typed. Exceptions are semmantic errors that arise at runtime. Microscheme makes use of the Arduino's built-in LED on digital pin 13 to give on-device indications of these situations. Generally, exceptions are not recoverable, and the device will need to be reset if an exception is raised. While it is possible to use digital pin 13 for general input and output, it is highly recommended to leave it free for exception indication.

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
StatusMeaningIndication
RUNProgram RunningNo Light
NVPNot a Valued ProcedureSingle Flashes
NARNumber of ARguments2 Flashes
NANNot A Number3 Flashes
NAPNot A Pair4 Flashes
NAVNot A Vector5 Flashes
OOBOut Of Bounds6 Flashes
DBZDivide By Zero7 Flashes
ERRCustom ExceptionContinuous Flashes
HALTProgram CompletedContinuous Light
43 | 44 |
Exception Details
45 |

NVP: A procedure application takes the form (proc X1 X2 ... Xn) where proc is an expression. At the time of application, if proc does not evaluate to a (valued) procedure, such as the result of a (lambda …) form, or a variable bound to a procedure, then NVP will be raised.

46 |

NAR: A procedure application takes the form (proc X1 X2 ... Xn) where X1 X2 ... Xn are arguments. At the time of application, if proc evaluates to a procedure taking m arguments, but m ≠ n, then NAR will be raised.

47 |

NAN: Indicates that an arithmetic operator (+, -, *, /, div, mod) received an argument that did not evaluate to a number.

48 |

NAP: Indicates that a pair operator (car, cdr, set-car!, set-cdr!) received an argument that did not evaluate to a pair.

49 |

NAV: Indicates that a vector operator (vector-ref, vector-set!) received an argument that did not evaluate to a vector.

50 |

OOB: Indicates that a vector operator (vector-ref, vector-set!) received an index that was outside the dimensions of the vector given.

51 |

DBZ: Indicates an attempt to divide by zero.

52 |

ERR: This exception is raised manually by the programmer. See (error) and (assert expr) in the language guide.

53 | 54 | 55 |
56 | 57 |
    58 |
  • «
  • 59 |
  • 1
  • 60 |
  • 2
  • 61 |
  • 3
  • 62 |
  • 4
  • 63 |
  • 5
  • 64 |
  • 6
  • 65 |
  • 7
  • 66 |
  • »
  • 67 |
68 | 69 | 70 | 71 |
72 |
73 |
74 | 75 |
76 | 96 |
97 |
98 |
99 | 100 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/old/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

Help

23 | 24 | 25 |
Frequently Asked Questions
26 |

There aren't any yet!

27 | 28 |
Contact Details
29 |

Feel free to contact me with questions, requests, and general feedback by emailing ryan [at] ryansuchocki [dot] co [dot] uk

30 | 31 | 32 | 33 |
34 |
35 |
36 | 37 |
38 | 58 |
59 |
60 |
61 | 62 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/old/img/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/old/img/hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/img/hello.png -------------------------------------------------------------------------------- /docs/old/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

microscheme.org

23 |

A functional programming language for the Arduino

24 | 25 |
Update Alert Version 0.8 now available, featuring arbitrary lambda nesting and multiple-include protection.
26 | 27 | 28 | 29 |
30 |

31 |

32 | 
33 | (include "libraries/list.ms")
34 | (include "libraries/io.ms")
35 | (include "libraries/lcd.ms")
36 | 
37 | (lcd_init)
38 | 
39 | (for-each-vector write "Hi, from Scheme!")
40 | 
41 |  
42 | 
43 |
44 | 45 | 46 |

Microscheme is a Scheme-like functional programming language, specifically targeting the Atmel 8-bit AVR microcontrollers, and designed to be used with the Arduino UNO and MEGA development boards. Microscheme is a ‘subset’ of Scheme in the sense that every valid microscheme program is also a valid Scheme program (with minor syntax substitutions). It can be characterised as compiled Scheme without the following features: first-class continuations, a macro system, variadic functions and full closures. These are deliberate shortcomings, and arise from the fact that the AVR-based Arduinos only have up to 8KB —Yes, Kilobytes!— of RAM. The overhead spared by leaving out those features means that the programmer is left with a useful amount of RAM to work with. The microscheme compiler is a hand-written recursive descent compiler, written in C, relying only on the C standard library. It is (slightly) novel among microcontroller-targeting Scheme implementations in that it compiles directly to assembly, rather than generating equivalent C code. Microscheme supports more than 80 fundemental forms, primitive and library functions out-of-the-box.

47 | 48 | 49 |
50 |
51 |
52 | 53 |
54 | 73 |
74 |
75 |
76 | 77 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.accordion.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.accordion = { 5 | name : 'accordion', 6 | 7 | version : '5.0.3', 8 | 9 | settings : { 10 | active_class: 'active', 11 | toggleable: true 12 | }, 13 | 14 | init : function (scope, method, options) { 15 | this.bindings(method, options); 16 | }, 17 | 18 | events : function () { 19 | $(this.scope).off('.accordion').on('click.fndtn.accordion', '[data-accordion] > dd > a', function (e) { 20 | var accordion = $(this).parent(), 21 | target = $('#' + this.href.split('#')[1]), 22 | siblings = $('> dd > .content', target.closest('[data-accordion]')), 23 | settings = accordion.parent().data('accordion-init'), 24 | active = $('> dd > .content.' + settings.active_class, accordion.parent()); 25 | 26 | e.preventDefault(); 27 | 28 | if (active[0] == target[0] && settings.toggleable) { 29 | return target.toggleClass(settings.active_class); 30 | } 31 | 32 | siblings.removeClass(settings.active_class); 33 | target.addClass(settings.active_class); 34 | }); 35 | }, 36 | 37 | off : function () {}, 38 | 39 | reflow : function () {} 40 | }; 41 | }(jQuery, this, this.document)); 42 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.alert.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.alert = { 5 | name : 'alert', 6 | 7 | version : '5.0.3', 8 | 9 | settings : { 10 | animation: 'fadeOut', 11 | speed: 300, // fade out speed 12 | callback: function (){} 13 | }, 14 | 15 | init : function (scope, method, options) { 16 | this.bindings(method, options); 17 | }, 18 | 19 | events : function () { 20 | $(this.scope).off('.alert').on('click.fndtn.alert', '[data-alert] a.close', function (e) { 21 | var alertBox = $(this).closest("[data-alert]"), 22 | settings = alertBox.data('alert-init') || Foundation.libs.alert.settings; 23 | 24 | e.preventDefault(); 25 | alertBox[settings.animation](settings.speed, function () { 26 | $(this).trigger('closed').remove(); 27 | settings.callback(); 28 | }); 29 | }); 30 | }, 31 | 32 | reflow : function () {} 33 | }; 34 | }(jQuery, this, this.document)); 35 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.dropdown.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.dropdown = { 5 | name : 'dropdown', 6 | 7 | version : '5.0.3', 8 | 9 | settings : { 10 | active_class: 'open', 11 | is_hover: false, 12 | opened: function(){}, 13 | closed: function(){} 14 | }, 15 | 16 | init : function (scope, method, options) { 17 | Foundation.inherit(this, 'throttle'); 18 | 19 | this.bindings(method, options); 20 | }, 21 | 22 | events : function (scope) { 23 | var self = this; 24 | 25 | $(this.scope) 26 | .off('.dropdown') 27 | .on('click.fndtn.dropdown', '[data-dropdown]', function (e) { 28 | var settings = $(this).data('dropdown-init') || self.settings; 29 | e.preventDefault(); 30 | 31 | self.closeall.call(self); 32 | 33 | if (!settings.is_hover || Modernizr.touch) self.toggle($(this)); 34 | }) 35 | .on('mouseenter.fndtn.dropdown', '[data-dropdown], [data-dropdown-content]', function (e) { 36 | var $this = $(this); 37 | clearTimeout(self.timeout); 38 | 39 | if ($this.data('dropdown')) { 40 | var dropdown = $('#' + $this.data('dropdown')), 41 | target = $this; 42 | } else { 43 | var dropdown = $this; 44 | target = $("[data-dropdown='" + dropdown.attr('id') + "']"); 45 | } 46 | 47 | var settings = target.data('dropdown-init') || self.settings; 48 | 49 | if($(e.target).data('dropdown') && settings.is_hover) { 50 | self.closeall.call(self); 51 | } 52 | 53 | if (settings.is_hover) self.open.apply(self, [dropdown, target]); 54 | }) 55 | .on('mouseleave.fndtn.dropdown', '[data-dropdown], [data-dropdown-content]', function (e) { 56 | var $this = $(this); 57 | self.timeout = setTimeout(function () { 58 | if ($this.data('dropdown')) { 59 | var settings = $this.data('dropdown-init') || self.settings; 60 | if (settings.is_hover) self.close.call(self, $('#' + $this.data('dropdown'))); 61 | } else { 62 | var target = $('[data-dropdown="' + $(this).attr('id') + '"]'), 63 | settings = target.data('dropdown-init') || self.settings; 64 | if (settings.is_hover) self.close.call(self, $this); 65 | } 66 | }.bind(this), 150); 67 | }) 68 | .on('click.fndtn.dropdown', function (e) { 69 | var parent = $(e.target).closest('[data-dropdown-content]'); 70 | 71 | if ($(e.target).data('dropdown') || $(e.target).parent().data('dropdown')) { 72 | return; 73 | } 74 | if (!($(e.target).data('revealId')) && 75 | (parent.length > 0 && ($(e.target).is('[data-dropdown-content]') || 76 | $.contains(parent.first()[0], e.target)))) { 77 | e.stopPropagation(); 78 | return; 79 | } 80 | 81 | self.close.call(self, $('[data-dropdown-content]')); 82 | }) 83 | .on('opened.fndtn.dropdown', '[data-dropdown-content]', function () { 84 | self.settings.opened.call(this); 85 | }) 86 | .on('closed.fndtn.dropdown', '[data-dropdown-content]', function () { 87 | self.settings.closed.call(this); 88 | }); 89 | 90 | $(window) 91 | .off('.dropdown') 92 | .on('resize.fndtn.dropdown', self.throttle(function () { 93 | self.resize.call(self); 94 | }, 50)).trigger('resize'); 95 | }, 96 | 97 | close: function (dropdown) { 98 | var self = this; 99 | dropdown.each(function () { 100 | if ($(this).hasClass(self.settings.active_class)) { 101 | $(this) 102 | .css(Foundation.rtl ? 'right':'left', '-99999px') 103 | .removeClass(self.settings.active_class); 104 | $(this).trigger('closed'); 105 | } 106 | }); 107 | }, 108 | 109 | closeall: function() { 110 | var self = this; 111 | $.each($('[data-dropdown-content]'), function() { 112 | self.close.call(self, $(this)) 113 | }); 114 | }, 115 | 116 | open: function (dropdown, target) { 117 | this 118 | .css(dropdown 119 | .addClass(this.settings.active_class), target); 120 | dropdown.trigger('opened'); 121 | }, 122 | 123 | toggle : function (target) { 124 | var dropdown = $('#' + target.data('dropdown')); 125 | if (dropdown.length === 0) { 126 | // No dropdown found, not continuing 127 | return; 128 | } 129 | 130 | this.close.call(this, $('[data-dropdown-content]').not(dropdown)); 131 | 132 | if (dropdown.hasClass(this.settings.active_class)) { 133 | this.close.call(this, dropdown); 134 | } else { 135 | this.close.call(this, $('[data-dropdown-content]')) 136 | this.open.call(this, dropdown, target); 137 | } 138 | }, 139 | 140 | resize : function () { 141 | var dropdown = $('[data-dropdown-content].open'), 142 | target = $("[data-dropdown='" + dropdown.attr('id') + "']"); 143 | 144 | if (dropdown.length && target.length) { 145 | this.css(dropdown, target); 146 | } 147 | }, 148 | 149 | css : function (dropdown, target) { 150 | var offset_parent = dropdown.offsetParent(), 151 | position = target.offset(); 152 | 153 | position.top -= offset_parent.offset().top; 154 | position.left -= offset_parent.offset().left; 155 | 156 | if (this.small()) { 157 | dropdown.css({ 158 | position : 'absolute', 159 | width: '95%', 160 | 'max-width': 'none', 161 | top: position.top + target.outerHeight() 162 | }); 163 | dropdown.css(Foundation.rtl ? 'right':'left', '2.5%'); 164 | } else { 165 | if (!Foundation.rtl && $(window).width() > dropdown.outerWidth() + target.offset().left) { 166 | var left = position.left; 167 | if (dropdown.hasClass('right')) { 168 | dropdown.removeClass('right'); 169 | } 170 | } else { 171 | if (!dropdown.hasClass('right')) { 172 | dropdown.addClass('right'); 173 | } 174 | var left = position.left - (dropdown.outerWidth() - target.outerWidth()); 175 | } 176 | 177 | dropdown.attr('style', '').css({ 178 | position : 'absolute', 179 | top: position.top + target.outerHeight(), 180 | left: left 181 | }); 182 | } 183 | 184 | return dropdown; 185 | }, 186 | 187 | small : function () { 188 | return matchMedia(Foundation.media_queries.small).matches && 189 | !matchMedia(Foundation.media_queries.medium).matches; 190 | }, 191 | 192 | off: function () { 193 | $(this.scope).off('.fndtn.dropdown'); 194 | $('html, body').off('.fndtn.dropdown'); 195 | $(window).off('.fndtn.dropdown'); 196 | $('[data-dropdown-content]').off('.fndtn.dropdown'); 197 | this.settings.init = false; 198 | }, 199 | 200 | reflow : function () {} 201 | }; 202 | }(jQuery, this, this.document)); 203 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.magellan.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.magellan = { 5 | name : 'magellan', 6 | 7 | version : '5.0.3', 8 | 9 | settings : { 10 | active_class: 'active', 11 | threshold: 0 12 | }, 13 | 14 | init : function (scope, method, options) { 15 | this.fixed_magellan = $("[data-magellan-expedition]"); 16 | this.magellan_placeholder = $('
').css({ 17 | height: this.fixed_magellan.outerHeight(true) 18 | }).hide().insertAfter(this.fixed_magellan); 19 | this.set_threshold(); 20 | this.set_active_class(method); 21 | this.last_destination = $('[data-magellan-destination]').last(); 22 | this.events(); 23 | }, 24 | 25 | events : function () { 26 | var self = this; 27 | 28 | $(this.scope) 29 | .off('.magellan') 30 | .on('arrival.fndtn.magellan', '[data-magellan-arrival]', function (e) { 31 | var $destination = $(this), 32 | $expedition = $destination.closest('[data-magellan-expedition]'), 33 | active_class = $expedition.attr('data-magellan-active-class') 34 | || self.settings.active_class; 35 | 36 | $destination 37 | .closest('[data-magellan-expedition]') 38 | .find('[data-magellan-arrival]') 39 | .not($destination) 40 | .removeClass(active_class); 41 | $destination.addClass(active_class); 42 | }); 43 | 44 | this.fixed_magellan 45 | .off('.magellan') 46 | .on('update-position.fndtn.magellan', function() { 47 | var $el = $(this); 48 | }) 49 | .trigger('update-position'); 50 | 51 | $(window) 52 | .off('.magellan') 53 | .on('resize.fndtn.magellan', function() { 54 | this.fixed_magellan.trigger('update-position'); 55 | }.bind(this)) 56 | .on('scroll.fndtn.magellan', function() { 57 | var windowScrollTop = $(window).scrollTop(); 58 | self.fixed_magellan.each(function() { 59 | var $expedition = $(this); 60 | if (typeof $expedition.data('magellan-top-offset') === 'undefined') { 61 | $expedition.data('magellan-top-offset', $expedition.offset().top); 62 | } 63 | if (typeof $expedition.data('magellan-fixed-position') === 'undefined') { 64 | $expedition.data('magellan-fixed-position', false); 65 | } 66 | var fixed_position = (windowScrollTop + self.settings.threshold) > $expedition.data("magellan-top-offset"); 67 | var attr = $expedition.attr('data-magellan-top-offset'); 68 | 69 | if ($expedition.data("magellan-fixed-position") != fixed_position) { 70 | $expedition.data("magellan-fixed-position", fixed_position); 71 | if (fixed_position) { 72 | $expedition.addClass('fixed'); 73 | $expedition.css({position:"fixed", top:0}); 74 | self.magellan_placeholder.show(); 75 | } else { 76 | $expedition.removeClass('fixed'); 77 | $expedition.css({position:"", top:""}); 78 | self.magellan_placeholder.hide(); 79 | } 80 | if (fixed_position && typeof attr != 'undefined' && attr != false) { 81 | $expedition.css({position:"fixed", top:attr + "px"}); 82 | } 83 | } 84 | }); 85 | }); 86 | 87 | 88 | if (this.last_destination.length > 0) { 89 | $(window).on('scroll.fndtn.magellan', function (e) { 90 | var windowScrollTop = $(window).scrollTop(), 91 | scrolltopPlusHeight = windowScrollTop + $(window).height(), 92 | lastDestinationTop = Math.ceil(self.last_destination.offset().top); 93 | 94 | $('[data-magellan-destination]').each(function () { 95 | var $destination = $(this), 96 | destination_name = $destination.attr('data-magellan-destination'), 97 | topOffset = $destination.offset().top - $destination.outerHeight(true) - windowScrollTop; 98 | if (topOffset <= self.settings.threshold) { 99 | $("[data-magellan-arrival='" + destination_name + "']").trigger('arrival'); 100 | } 101 | // In large screens we may hit the bottom of the page and dont reach the top of the last magellan-destination, so lets force it 102 | if (scrolltopPlusHeight >= $(self.scope).height() && lastDestinationTop > windowScrollTop && lastDestinationTop < scrolltopPlusHeight) { 103 | $('[data-magellan-arrival]').last().trigger('arrival'); 104 | } 105 | }); 106 | }); 107 | } 108 | }, 109 | 110 | set_threshold : function () { 111 | if (typeof this.settings.threshold !== 'number') { 112 | this.settings.threshold = (this.fixed_magellan.length > 0) ? 113 | this.fixed_magellan.outerHeight(true) : 0; 114 | } 115 | }, 116 | 117 | set_active_class : function (options) { 118 | if (options && options.active_class && typeof options.active_class === 'string') { 119 | this.settings.active_class = options.active_class; 120 | } 121 | }, 122 | 123 | off : function () { 124 | $(this.scope).off('.fndtn.magellan'); 125 | $(window).off('.fndtn.magellan'); 126 | }, 127 | 128 | reflow : function () {} 129 | }; 130 | }(jQuery, this, this.document)); 131 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.offcanvas.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.offcanvas = { 5 | name : 'offcanvas', 6 | 7 | version : '5.0.3', 8 | 9 | settings : {}, 10 | 11 | init : function (scope, method, options) { 12 | this.events(); 13 | }, 14 | 15 | events : function () { 16 | $(this.scope).off('.offcanvas') 17 | .on('click.fndtn.offcanvas', '.left-off-canvas-toggle', function (e) { 18 | e.preventDefault(); 19 | $(this).closest('.off-canvas-wrap').toggleClass('move-right'); 20 | }) 21 | .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e) { 22 | e.preventDefault(); 23 | $(".off-canvas-wrap").removeClass("move-right"); 24 | }) 25 | .on('click.fndtn.offcanvas', '.right-off-canvas-toggle', function (e) { 26 | e.preventDefault(); 27 | $(this).closest(".off-canvas-wrap").toggleClass("move-left"); 28 | }) 29 | .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e) { 30 | e.preventDefault(); 31 | $(".off-canvas-wrap").removeClass("move-left"); 32 | }); 33 | }, 34 | 35 | reflow : function () {} 36 | }; 37 | }(jQuery, this, this.document)); 38 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.tab.js: -------------------------------------------------------------------------------- 1 | /*jslint unparam: true, browser: true, indent: 2 */ 2 | ;(function ($, window, document, undefined) { 3 | 'use strict'; 4 | 5 | Foundation.libs.tab = { 6 | name : 'tab', 7 | 8 | version : '5.0.3', 9 | 10 | settings : { 11 | active_class: 'active', 12 | callback : function () {} 13 | }, 14 | 15 | init : function (scope, method, options) { 16 | this.bindings(method, options); 17 | }, 18 | 19 | events : function () { 20 | $(this.scope).off('.tab').on('click.fndtn.tab', '[data-tab] > dd > a', function (e) { 21 | e.preventDefault(); 22 | 23 | var tab = $(this).parent(), 24 | tabs = tab.closest('[data-tab]'), 25 | target = $('#' + this.href.split('#')[1]), 26 | siblings = tab.siblings(), 27 | settings = tabs.data('tab-init'); 28 | 29 | // allow usage of data-tab-content attribute instead of href 30 | if ($(this).data('tab-content')) { 31 | target = $('#' + $(this).data('tab-content').split('#')[1]); 32 | } 33 | 34 | tab.addClass(settings.active_class).trigger('opened'); 35 | siblings.removeClass(settings.active_class); 36 | target.siblings().removeClass(settings.active_class).end().addClass(settings.active_class); 37 | settings.callback(tab); 38 | tabs.trigger('toggled', [tab]); 39 | }); 40 | }, 41 | 42 | off : function () {}, 43 | 44 | reflow : function () {} 45 | }; 46 | }(jQuery, this, this.document)); 47 | -------------------------------------------------------------------------------- /docs/old/js/foundation/foundation.tooltip.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.tooltip = { 5 | name : 'tooltip', 6 | 7 | version : '5.0.3', 8 | 9 | settings : { 10 | additional_inheritable_classes : [], 11 | tooltip_class : '.tooltip', 12 | append_to: 'body', 13 | touch_close_text: 'Tap To Close', 14 | disable_for_touch: false, 15 | tip_template : function (selector, content) { 16 | return '' + content + ''; 19 | } 20 | }, 21 | 22 | cache : {}, 23 | 24 | init : function (scope, method, options) { 25 | this.bindings(method, options); 26 | }, 27 | 28 | events : function () { 29 | var self = this; 30 | 31 | if (Modernizr.touch) { 32 | $(this.scope) 33 | .off('.tooltip') 34 | .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip', 35 | '[data-tooltip]', function (e) { 36 | var settings = $.extend({}, self.settings, self.data_options($(this))); 37 | if (!settings.disable_for_touch) { 38 | e.preventDefault(); 39 | $(settings.tooltip_class).hide(); 40 | self.showOrCreateTip($(this)); 41 | } 42 | }) 43 | .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip', 44 | this.settings.tooltip_class, function (e) { 45 | e.preventDefault(); 46 | $(this).fadeOut(150); 47 | }); 48 | } else { 49 | $(this.scope) 50 | .off('.tooltip') 51 | .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip', 52 | '[data-tooltip]', function (e) { 53 | var $this = $(this); 54 | 55 | if (/enter|over/i.test(e.type)) { 56 | self.showOrCreateTip($this); 57 | } else if (e.type === 'mouseout' || e.type === 'mouseleave') { 58 | self.hide($this); 59 | } 60 | }); 61 | } 62 | }, 63 | 64 | showOrCreateTip : function ($target) { 65 | var $tip = this.getTip($target); 66 | 67 | if ($tip && $tip.length > 0) { 68 | return this.show($target); 69 | } 70 | 71 | return this.create($target); 72 | }, 73 | 74 | getTip : function ($target) { 75 | var selector = this.selector($target), 76 | tip = null; 77 | 78 | if (selector) { 79 | tip = $('span[data-selector="' + selector + '"]' + this.settings.tooltip_class); 80 | } 81 | 82 | return (typeof tip === 'object') ? tip : false; 83 | }, 84 | 85 | selector : function ($target) { 86 | var id = $target.attr('id'), 87 | dataSelector = $target.attr('data-tooltip') || $target.attr('data-selector'); 88 | 89 | if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') { 90 | dataSelector = 'tooltip' + Math.random().toString(36).substring(7); 91 | $target.attr('data-selector', dataSelector); 92 | } 93 | 94 | return (id && id.length > 0) ? id : dataSelector; 95 | }, 96 | 97 | create : function ($target) { 98 | var $tip = $(this.settings.tip_template(this.selector($target), $('
').html($target.attr('title')).html())), 99 | classes = this.inheritable_classes($target); 100 | 101 | $tip.addClass(classes).appendTo(this.settings.append_to); 102 | if (Modernizr.touch) { 103 | $tip.append(''+this.settings.touch_close_text+''); 104 | } 105 | $target.removeAttr('title').attr('title',''); 106 | this.show($target); 107 | }, 108 | 109 | reposition : function (target, tip, classes) { 110 | var width, nub, nubHeight, nubWidth, column, objPos; 111 | 112 | tip.css('visibility', 'hidden').show(); 113 | 114 | width = target.data('width'); 115 | nub = tip.children('.nub'); 116 | nubHeight = nub.outerHeight(); 117 | nubWidth = nub.outerHeight(); 118 | 119 | tip.css({'width' : (width) ? width : 'auto'}); 120 | 121 | objPos = function (obj, top, right, bottom, left, width) { 122 | return obj.css({ 123 | 'top' : (top) ? top : 'auto', 124 | 'bottom' : (bottom) ? bottom : 'auto', 125 | 'left' : (left) ? left : 'auto', 126 | 'right' : (right) ? right : 'auto' 127 | }).end(); 128 | }; 129 | 130 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left); 131 | 132 | if (this.small()) { 133 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, $(this.scope).width()); 134 | tip.addClass('tip-override'); 135 | objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left); 136 | } else { 137 | var left = target.offset().left; 138 | if (Foundation.rtl) { 139 | left = target.offset().left + target.offset().width - tip.outerWidth(); 140 | } 141 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left); 142 | tip.removeClass('tip-override'); 143 | if (classes && classes.indexOf('tip-top') > -1) { 144 | objPos(tip, (target.offset().top - tip.outerHeight() - 10), 'auto', 'auto', left) 145 | .removeClass('tip-override'); 146 | } else if (classes && classes.indexOf('tip-left') > -1) { 147 | objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight)) 148 | .removeClass('tip-override'); 149 | } else if (classes && classes.indexOf('tip-right') > -1) { 150 | objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight)) 151 | .removeClass('tip-override'); 152 | } 153 | } 154 | 155 | tip.css('visibility', 'visible').hide(); 156 | }, 157 | 158 | small : function () { 159 | return matchMedia(Foundation.media_queries.small).matches; 160 | }, 161 | 162 | inheritable_classes : function (target) { 163 | var inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'noradius'].concat(this.settings.additional_inheritable_classes), 164 | classes = target.attr('class'), 165 | filtered = classes ? $.map(classes.split(' '), function (el, i) { 166 | if ($.inArray(el, inheritables) !== -1) { 167 | return el; 168 | } 169 | }).join(' ') : ''; 170 | 171 | return $.trim(filtered); 172 | }, 173 | 174 | show : function ($target) { 175 | var $tip = this.getTip($target); 176 | 177 | this.reposition($target, $tip, $target.attr('class')); 178 | $tip.fadeIn(150); 179 | }, 180 | 181 | hide : function ($target) { 182 | var $tip = this.getTip($target); 183 | 184 | $tip.fadeOut(150); 185 | }, 186 | 187 | // deprecate reload 188 | reload : function () { 189 | var $self = $(this); 190 | 191 | return ($self.data('fndtn-tooltips')) ? $self.foundationTooltips('destroy').foundationTooltips('init') : $self.foundationTooltips('init'); 192 | }, 193 | 194 | off : function () { 195 | $(this.scope).off('.fndtn.tooltip'); 196 | $(this.settings.tooltip_class).each(function (i) { 197 | $('[data-tooltip]').get(i).attr('title', $(this).text()); 198 | }).remove(); 199 | }, 200 | 201 | reflow : function () {} 202 | }; 203 | }(jQuery, this, this.document)); 204 | -------------------------------------------------------------------------------- /docs/old/js/modernizr.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-inlinesvg-svg-svgclippaths-touch-shiv-mq-cssclasses-teststyles-prefixes-ie8compat-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function y(a){j.cssText=a}function z(a,b){return y(m.join(a+";")+(b||""))}function A(a,b){return typeof a===b}function B(a,b){return!!~(""+a).indexOf(b)}function C(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:A(f,"function")?f.bind(d||b):f}return!1}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n={svg:"http://www.w3.org/2000/svg"},o={},p={},q={},r=[],s=r.slice,t,u=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["­",'"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},v=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return u("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},w={}.hasOwnProperty,x;!A(w,"undefined")&&!A(w.call,"undefined")?x=function(a,b){return w.call(a,b)}:x=function(a,b){return b in a&&A(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=s.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(s.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(s.call(arguments)))};return e}),o.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:u(["@media (",m.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},o.svg=function(){return!!b.createElementNS&&!!b.createElementNS(n.svg,"svg").createSVGRect},o.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==n.svg},o.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(l.call(b.createElementNS(n.svg,"clipPath")))};for(var D in o)x(o,D)&&(t=D.toLowerCase(),e[t]=o[D](),r.push((e[t]?"":"no-")+t));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)x(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},y(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=m,e.mq=v,e.testStyles=u,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+r.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f0,FastClick.prototype.deviceIsIOS=/iP(ad|hone|od)/.test(navigator.userAgent),FastClick.prototype.deviceIsIOS4=FastClick.prototype.deviceIsIOS&&/OS 4_\d(_\d)?/.test(navigator.userAgent),FastClick.prototype.deviceIsIOSWithBadTarget=FastClick.prototype.deviceIsIOS&&/OS ([6-9]|\d{2})_\d/.test(navigator.userAgent),FastClick.prototype.needsClick=function(a){"use strict";switch(a.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(a.disabled)return!0;break;case"input":if(this.deviceIsIOS&&"file"===a.type||a.disabled)return!0;break;case"label":case"video":return!0}return/\bneedsclick\b/.test(a.className)},FastClick.prototype.needsFocus=function(a){"use strict";switch(a.nodeName.toLowerCase()){case"textarea":return!0;case"select":return!this.deviceIsAndroid;case"input":switch(a.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return!1}return!a.disabled&&!a.readOnly;default:return/\bneedsfocus\b/.test(a.className)}},FastClick.prototype.sendClick=function(a,b){"use strict";var c,d;document.activeElement&&document.activeElement!==a&&document.activeElement.blur(),d=b.changedTouches[0],c=document.createEvent("MouseEvents"),c.initMouseEvent(this.determineEventType(a),!0,!0,window,1,d.screenX,d.screenY,d.clientX,d.clientY,!1,!1,!1,!1,0,null),c.forwardedTouchEvent=!0,a.dispatchEvent(c)},FastClick.prototype.determineEventType=function(a){"use strict";return this.deviceIsAndroid&&"select"===a.tagName.toLowerCase()?"mousedown":"click"},FastClick.prototype.focus=function(a){"use strict";var b;this.deviceIsIOS&&a.setSelectionRange&&0!==a.type.indexOf("date")&&"time"!==a.type?(b=a.value.length,a.setSelectionRange(b,b)):a.focus()},FastClick.prototype.updateScrollParent=function(a){"use strict";var b,c;if(b=a.fastClickScrollParent,!b||!b.contains(a)){c=a;do{if(c.scrollHeight>c.offsetHeight){b=c,a.fastClickScrollParent=c;break}c=c.parentElement}while(c)}b&&(b.fastClickLastScrollTop=b.scrollTop)},FastClick.prototype.getTargetElementFromEventTarget=function(a){"use strict";return a.nodeType===Node.TEXT_NODE?a.parentNode:a},FastClick.prototype.onTouchStart=function(a){"use strict";var b,c,d;if(a.targetTouches.length>1)return!0;if(b=this.getTargetElementFromEventTarget(a.target),c=a.targetTouches[0],this.deviceIsIOS){if(d=window.getSelection(),d.rangeCount&&!d.isCollapsed)return!0;if(!this.deviceIsIOS4){if(c.identifier===this.lastTouchIdentifier)return a.preventDefault(),!1;this.lastTouchIdentifier=c.identifier,this.updateScrollParent(b)}}return this.trackingClick=!0,this.trackingClickStart=a.timeStamp,this.targetElement=b,this.touchStartX=c.pageX,this.touchStartY=c.pageY,a.timeStamp-this.lastClickTime<200&&a.preventDefault(),!0},FastClick.prototype.touchHasMoved=function(a){"use strict";var b=a.changedTouches[0],c=this.touchBoundary;return Math.abs(b.pageX-this.touchStartX)>c||Math.abs(b.pageY-this.touchStartY)>c?!0:!1},FastClick.prototype.onTouchMove=function(a){"use strict";return this.trackingClick?((this.targetElement!==this.getTargetElementFromEventTarget(a.target)||this.touchHasMoved(a))&&(this.trackingClick=!1,this.targetElement=null),!0):!0},FastClick.prototype.findControl=function(a){"use strict";return void 0!==a.control?a.control:a.htmlFor?document.getElementById(a.htmlFor):a.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")},FastClick.prototype.onTouchEnd=function(a){"use strict";var b,c,d,e,f,g=this.targetElement;if(!this.trackingClick)return!0;if(a.timeStamp-this.lastClickTime<200)return this.cancelNextClick=!0,!0;if(this.cancelNextClick=!1,this.lastClickTime=a.timeStamp,c=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,this.deviceIsIOSWithBadTarget&&(f=a.changedTouches[0],g=document.elementFromPoint(f.pageX-window.pageXOffset,f.pageY-window.pageYOffset)||g,g.fastClickScrollParent=this.targetElement.fastClickScrollParent),d=g.tagName.toLowerCase(),"label"===d){if(b=this.findControl(g)){if(this.focus(g),this.deviceIsAndroid)return!1;g=b}}else if(this.needsFocus(g))return a.timeStamp-c>100||this.deviceIsIOS&&window.top!==window&&"input"===d?(this.targetElement=null,!1):(this.focus(g),this.deviceIsIOS4&&"select"===d||(this.targetElement=null,a.preventDefault()),!1);return this.deviceIsIOS&&!this.deviceIsIOS4&&(e=g.fastClickScrollParent,e&&e.fastClickLastScrollTop!==e.scrollTop)?!0:(this.needsClick(g)||(a.preventDefault(),this.sendClick(g,a)),!1)},FastClick.prototype.onTouchCancel=function(){"use strict";this.trackingClick=!1,this.targetElement=null},FastClick.prototype.onMouse=function(a){"use strict";return this.targetElement?a.forwardedTouchEvent?!0:a.cancelable?!this.needsClick(this.targetElement)||this.cancelNextClick?(a.stopImmediatePropagation?a.stopImmediatePropagation():a.propagationStopped=!0,a.stopPropagation(),a.preventDefault(),!1):!0:!0:!0},FastClick.prototype.onClick=function(a){"use strict";var b;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):"submit"===a.target.type&&0===a.detail?!0:(b=this.onMouse(a),b||(this.targetElement=null),b)},FastClick.prototype.destroy=function(){"use strict";var a=this.layer;this.deviceIsAndroid&&(a.removeEventListener("mouseover",this.onMouse,!0),a.removeEventListener("mousedown",this.onMouse,!0),a.removeEventListener("mouseup",this.onMouse,!0)),a.removeEventListener("click",this.onClick,!0),a.removeEventListener("touchstart",this.onTouchStart,!1),a.removeEventListener("touchmove",this.onTouchMove,!1),a.removeEventListener("touchend",this.onTouchEnd,!1),a.removeEventListener("touchcancel",this.onTouchCancel,!1)},FastClick.notNeeded=function(a){"use strict";var b,c;if("undefined"==typeof window.ontouchstart)return!0;if(c=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!FastClick.prototype.deviceIsAndroid)return!0;if(b=document.querySelector("meta[name=viewport]")){if(-1!==b.content.indexOf("user-scalable=no"))return!0;if(c>31&&window.innerWidth<=window.screen.width)return!0}}return"none"===a.style.msTouchAction?!0:!1},FastClick.attach=function(a){"use strict";return new FastClick(a)},"undefined"!=typeof define&&define.amd?define(function(){"use strict";return FastClick}):"undefined"!=typeof module&&module.exports?(module.exports=FastClick.attach,module.exports.FastClick=FastClick):window.FastClick=FastClick; 10 | -------------------------------------------------------------------------------- /docs/old/js/vendor/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.4.0 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2013 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{a=decodeURIComponent(a.replace(g," "))}catch(b){return}try{return h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setDate(k.getDate()+j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0!==a.cookie(b)?(a.cookie(b,"",a.extend({},c,{expires:-1})),!0):!1}}); 9 | -------------------------------------------------------------------------------- /docs/old/js/vendor/placeholder.js: -------------------------------------------------------------------------------- 1 | /*! http://mths.be/placeholder v2.0.7 by @mathias */ 2 | !function(a,b,c){function d(a){var b={},d=/^jQuery\d+$/;return c.each(a.attributes,function(a,c){c.specified&&!d.test(c.name)&&(b[c.name]=c.value)}),b}function e(a,d){var e=this,f=c(e);if(e.value==f.attr("placeholder")&&f.hasClass("placeholder"))if(f.data("placeholder-password")){if(f=f.hide().next().show().attr("id",f.removeAttr("id").data("placeholder-id")),a===!0)return f[0].value=d;f.focus()}else e.value="",f.removeClass("placeholder"),e==b.activeElement&&e.select()}function f(){var a,b=this,f=c(b),g=this.id;if(""==b.value){if("password"==b.type){if(!f.data("placeholder-textinput")){try{a=f.clone().attr({type:"text"})}catch(h){a=c("").attr(c.extend(d(this),{type:"text"}))}a.removeAttr("name").data({"placeholder-password":!0,"placeholder-id":g}).bind("focus.placeholder",e),f.data({"placeholder-textinput":a,"placeholder-id":g}).before(a)}f=f.removeAttr("id").hide().prev().attr("id",g).show()}f.addClass("placeholder"),f[0].value=f.attr("placeholder")}else f.removeClass("placeholder")}var g,h,i="placeholder"in b.createElement("input"),j="placeholder"in b.createElement("textarea"),k=c.fn,l=c.valHooks;i&&j?(h=k.placeholder=function(){return this},h.input=h.textarea=!0):(h=k.placeholder=function(){var a=this;return a.filter((i?"textarea":":input")+"[placeholder]").not(".placeholder").bind({"focus.placeholder":e,"blur.placeholder":f}).data("placeholder-enabled",!0).trigger("blur.placeholder"),a},h.input=i,h.textarea=j,g={get:function(a){var b=c(a);return b.data("placeholder-enabled")&&b.hasClass("placeholder")?"":a.value},set:function(a,d){var g=c(a);return g.data("placeholder-enabled")?(""==d?(a.value=d,a!=b.activeElement&&f.call(a)):g.hasClass("placeholder")?e.call(a,!0,d)||(a.value=d):a.value=d,g):a.value=d}},i||(l.input=g),j||(l.textarea=g),c(function(){c(b).delegate("form","submit.placeholder",function(){var a=c(".placeholder",this).each(e);setTimeout(function(){a.each(f)},10)})}),c(a).bind("beforeunload.placeholder",function(){c(".placeholder").each(function(){this.value=""})}))}(this,document,jQuery); 3 | -------------------------------------------------------------------------------- /docs/old/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/logo.png -------------------------------------------------------------------------------- /docs/old/logo.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/logo.xcf -------------------------------------------------------------------------------- /docs/old/logosmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/logosmall.png -------------------------------------------------------------------------------- /docs/old/logosquare.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/logosquare.xcf -------------------------------------------------------------------------------- /docs/old/mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/old/mini.png -------------------------------------------------------------------------------- /docs/old/sam.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/old/workflow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | microscheme.org 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |

microscheme Workflow

23 |

From source code to the Arduino

24 | 25 |

The basic workflow is as follows:

26 |
  1. Write your program and save it as myprogram.ms
  2. 27 |
  3. Compile it using microscheme, resulting in myprogram.s
  4. 28 |
  5. Assemble it using avr-gcc, resulting in myprogram.elf
  6. 29 |
  7. Convert it to HEX format using avr-objcopy, resulting in myprogram.hex
  8. 30 |
  9. Upload it to the arduino using avrdude
31 | 32 |

However, this process is quite laborious, and the combination of arguments given to each tool can be complicated. Therefore, microscheme comes with a Makefile designed to automate this process. The simplified workflow is:

33 |
  1. Write your program, and save it as myprogram.ms
  2. 34 |
  3. Determine the path of the special device file allocated to the Arduino. This will be something like /dev/ttyACM0 or /dev/ttyUSB0.
  4. 35 |
  5. Execute   $ make upload MODEL=… DEV=…
    Filling in either MEGA or UNO for model, and the DEV path from step 2
36 | 37 | 38 |
39 |
40 |
41 | 42 |
43 | 62 |
63 |
64 |
65 | 66 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /docs/static/dissertation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryansuchocki/microscheme/aeee3db837b6eefd78b73696e9cbf4066da4f6a6/docs/static/dissertation.pdf -------------------------------------------------------------------------------- /emulator.scm: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Primitives for other scheme implementations 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | ;; This file defines microscheme-specific syntax/primitives, 8 | ;; and emulates a set of digital I/O registers, so that you 9 | ;; can run Microscheme programs on other Scheme implementations 10 | ;; (For example, on your PC). 11 | 12 | (define-syntax free! 13 | (syntax-rules () 14 | ((free! body ...) 15 | (begin body ...)))) 16 | 17 | (define-syntax @if-model-uno 18 | (syntax-rules () 19 | ((@if-model-uno body) 20 | body))) 21 | 22 | (define-syntax @if-model-mega 23 | (syntax-rules () 24 | ((@if-model-mega body) 25 | #f))) 26 | 27 | (define-syntax @if-model-leo 28 | (syntax-rules () 29 | ((@if-model-leo body) 30 | #f))) 31 | 32 | (define ¬ not) 33 | (define include load) 34 | (define (div x y) (floor (/ x y))) 35 | (define mod modulo) 36 | (define (assert x) (if (not x) (error "ms" "assertion failed"))) 37 | (define (error) (error "ms" "custom-error")) 38 | (define (stacksize) 0) 39 | (define (heapsize) 0) 40 | (define (pause x) (display "Pause for ") (display x) (display " milliseconds...") (display #\newline)) ;; TODO 41 | (define (micropause x) (display "Pause for ") (display x) (display " microseconds...") (display #\newline)) ;; TODO 42 | (define (serial-send x) (display "Serial: ") (display x) (display #\newline)) 43 | (define (char->number x) x) ;; TODO 44 | 45 | (define digital-state #f) 46 | (define set-digital-state #f) 47 | 48 | (load "src/stdlib.ms") 49 | 50 | (define ddr-state (vector #f #f #f #f #f #f #f #f #f #f #f #f #f)) 51 | (define pin-state (vector #f #f #f #f #f #f #f #f #f #f #f #f #f)) 52 | 53 | (define (showstate) 54 | (for 0 (vector-last ddr-state) (lambda (i) 55 | (if (vector-ref ddr-state i) 56 | (if (vector-ref pin-state i) 57 | (display "H") 58 | (display "L")) 59 | (display ".")))) 60 | (display #\newline)) 61 | 62 | 63 | (define (set-ddr apin val) (vector-set! ddr-state apin val) (showstate) apin) 64 | (define (set-pin apin val) (vector-set! pin-state apin val) (showstate) apin) 65 | (define (output? apin) (vector-ref ddr-state apin)) 66 | (define (high? apin) (vector-ref pin-state apin)) 67 | 68 | (display "Microscheme emulation ready...") 69 | #t -------------------------------------------------------------------------------- /examples/BLINK.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; LED blinking example 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (define led-pin (output 13)) 8 | 9 | (define (loop) 10 | (toggle led-pin) 11 | (pause 1000)) 12 | 13 | (forever loop) 14 | -------------------------------------------------------------------------------- /examples/GERALD.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Fractal-drawing robot example 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (define mleft (list 4 5 6 7)) 8 | (define mright (list 8 9 10 11)) 9 | 10 | (define reverse-mleft (reverse mleft)) 11 | (define reverse-mright (reverse mright)) 12 | 13 | (for-each output mleft) 14 | (for-each output mright) 15 | 16 | (define (cycle2 m1 m2) 17 | (or (null? m1) (null? m2) 18 | (begin 19 | (high (car m1)) 20 | (high (car m2)) 21 | (pause 4) 22 | (low (car m1)) 23 | (low (car m2)) 24 | (cycle2 (cdr m1) (cdr m2))))) 25 | 26 | (define (forward x) (free! 27 | (for 1 (* x 32) (lambda (_) 28 | (cycle2 mleft mright))))) 29 | 30 | (define (right x) (free! 31 | (for 1 (div (* x 256) 45) (lambda (_) 32 | (cycle2 mleft reverse-mright))))) 33 | 34 | (define (left x) (free! 35 | (for 1 (div (* x 256) 45) (lambda (_) 36 | (cycle2 reverse-mleft mright))))) 37 | 38 | (define (segment level) 39 | (if (zero? level) 40 | (forward 3) 41 | (begin 42 | (segment (- level 1)) 43 | (left 60) 44 | (segment (- level 1)) 45 | (right 120) 46 | (segment (- level 1)) 47 | (left 60) 48 | (segment (- level 1))))) 49 | 50 | (segment 2) -------------------------------------------------------------------------------- /examples/blink-led-morse.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Morse-code-blinking LED example 3 | ;; (C) 2021 Ryan Suchocki, @ardumont et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (define led-pin (output 13)) 8 | 9 | (define long-pulse 500) 10 | (define short-pulse 250) 11 | 12 | ;; make the led blink 13 | (define (blink time) 14 | (high led-pin) 15 | (pause time) 16 | (low led-pin) 17 | (pause time)) 18 | 19 | ;; letter is a list of 0 and 1 20 | (define (blink-letter letter) 21 | (map (lambda (signal) 22 | (blink (if (eq? 0 signal) short-pulse long-pulse))) 23 | letter)) 24 | 25 | (define (blink-sos) 26 | ;; s 27 | (blink-letter (list 0 0 0)) 28 | ;; o 29 | (blink-letter (list 1 1 1)) 30 | ;; s 31 | (blink-letter (list 0 0 0))) 32 | 33 | ;; some time after the firmware flashing 34 | (pause 2000) 35 | 36 | ;; let the led call help 37 | (blink-sos) 38 | 39 | ;; shutdown the led 40 | (pause 0) 41 | -------------------------------------------------------------------------------- /examples/clock.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Clock example 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (define anodes (vector 2 3 4 5)) 8 | (define cathodes (vector 22 26 24 28 32 36 30 34)) 9 | 10 | (define db (vector #t #t #t #t #t #t #t #t)) 11 | 12 | (define digit (vector 13 | (vector #t #f #f #f #f #f #f #t) 14 | (vector #t #t #t #t #t #f #f #t) 15 | (vector #t #f #f #t #f #f #t #f) 16 | (vector #t #f #t #t #f #f #f #f) 17 | (vector #t #t #t #f #t #f #f #f) 18 | (vector #t #f #t #f #f #t #f #f) 19 | (vector #t #f #f #f #f #t #f #f) 20 | (vector #t #t #t #f #f #f #f #t) 21 | (vector #t #f #f #f #f #f #f #f) 22 | (vector #t #f #t #f #f #f #f #f))) 23 | 24 | (define digits (vector 0 0 0 0)) 25 | 26 | (define (set-cathodes bits i) 27 | (set-pin (vector-ref cathodes i) (vector-ref bits i)) 28 | (if (< i 7) (set-cathodes bits (+ i 1)))) 29 | 30 | (define (disp x y z w) 31 | (set-cathodes (vector-ref digit (vector-ref digits x)) 0) 32 | 33 | (high (vector-ref anodes x)) 34 | (pause 5) 35 | (low (vector-ref anodes x)) 36 | 37 | (if (= z 95) 38 | (begin 39 | (set! z 0) 40 | (set! w (not w)) 41 | (set-pin 40 w)) 42 | (set! z (+ z 1))) 43 | 44 | (if (< y 11340) (disp (if (= x 3) 0 (+ x 1)) (+ y 1) z w))) 45 | 46 | (define mins 2) 47 | (define secs 26) 48 | 49 | (define (go) 50 | (vector-set! digits 0 (mod (div mins 10) 10)) 51 | (vector-set! digits 1 (mod mins 10)) 52 | 53 | (vector-set! digits 2 (mod (div secs 10) 10)) 54 | (vector-set! digits 3 (mod secs 10)) 55 | 56 | (disp 0 0 0 #t) 57 | (set! secs (+ secs 1)) 58 | (if (= secs 60) (begin (set! secs 0) (set! mins (+ mins 1)))) 59 | (if (= mins 24) (set! mins 0)) 60 | (go)) 61 | 62 | (for-each-vector output anodes) 63 | (for-each-vector low anodes) 64 | (for-each-vector output cathodes) 65 | (for-each-vector low cathodes) 66 | 67 | (output 40) 68 | (output 42) 69 | (low 42) 70 | (high 40) 71 | 72 | (pause 220) 73 | (go) 74 | -------------------------------------------------------------------------------- /examples/fade.ms: -------------------------------------------------------------------------------- 1 | ;; =============================== Microscheme =============================== 2 | ;; Fading LED example for the Arduino UNO (or NANO) 3 | ;; See https://docs.arduino.cc/built-in-examples/basics/Fade 4 | ;; (C) 2021 Ryan Suchocki, et al. 5 | ;; http://github.com/ryansuchocki/microscheme 6 | ;; 7 | 8 | ;; Initialization to use the analog pins 9 | (analog-init) 10 | 11 | ;; LED connected on pin 9 12 | (define led 9) 13 | (output led) 14 | 15 | (define fade-amount 5) 16 | 17 | (define (loop brightness add?) 18 | (if (and add? (> (+ brightness fade-amount) 255)) 19 | (loop (- brightness fade-amount) #f) 20 | (if (and (not add?) (< brightness fade-amount)) 21 | (loop (+ brightness fade-amount) #t) 22 | (begin 23 | (analog-write led brightness) 24 | (pause 30) 25 | (loop (if add? 26 | (+ brightness fade-amount) 27 | (- brightness fade-amount)) 28 | add?))))) 29 | 30 | (loop 0 #t) 31 | -------------------------------------------------------------------------------- /examples/helloworld.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; LCD Hello World example 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (include "libraries/lcd.ms") 8 | (lcd-init) 9 | 10 | (print "Hello World!") 11 | -------------------------------------------------------------------------------- /examples/marquee.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Marquee example 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (include "libraries/lcd.ms") 8 | 9 | (lcd-init) 10 | 11 | (define marquee "Hello, world! ") 12 | 13 | (define (rotate vect) 14 | (free! 15 | (let ((carry (vector-ref vect 0))) 16 | (for 0 (- (vector-length vect) 2) 17 | (lambda (i) 18 | (vector-set! vect i (vector-ref vect (+ i 1))))) 19 | (vector-set! vect (vector-last vect) carry)))) 20 | 21 | (define (loop) 22 | (set-cursor 0 0) 23 | (print marquee) 24 | (pause 500) 25 | (rotate marquee)) 26 | 27 | (forever loop) -------------------------------------------------------------------------------- /examples/music.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Musical stepper motor example 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (define mleft (list 4 5 6 7)) 8 | (for-each output mleft) 9 | 10 | (define (cycle m1 x) 11 | (or (null? m1) 12 | (begin 13 | (high (car m1)) 14 | (micropause x) 15 | (low (car m1)) 16 | (cycle (cdr m1) x)))) 17 | 18 | ;; In theory, this is an A# scale: 19 | (define scale (vector 1480 1319 1175 1109 988 880 784 740)) 20 | (define period (* 100 (vector-ref scale 0))) 21 | 22 | (define (note x l) 23 | (for 0 (* l (div period x)) (lambda (_) 24 | (cycle mleft x)))) 25 | 26 | ;; Twinkle twinkle, little star 27 | (define notes (list 0 0 4 4 5 5 4 3 3 2 2 1 1 0 4 4 3 3 2 2 1 4 4 3 3 2 2 1 0 0 4 4 5 5 4 3 3 2 2 1 1 0 )) 28 | (define lengths (list 5 5 5 5 5 5 10 5 5 5 5 5 5 10 5 5 5 5 5 5 10 5 5 5 5 5 5 10 5 5 5 5 5 5 10 5 5 5 5 5 5 10)) 29 | 30 | (define (play x y) 31 | (note (vector-ref scale (car x)) (car y)) 32 | (pause 100) 33 | (or (null? (cdr x)) (null? (cdr y)) 34 | (play (cdr x) (cdr y)))) 35 | 36 | (play notes lengths) 37 | 38 | -------------------------------------------------------------------------------- /examples/serial.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Serial comms examples 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | ;; The available methods 8 | 9 | ;; (serial-init baud) 10 | ;; Initialises the serial connection. Baud rate must be given in 100s of bits per second. 11 | ;; For example, (serial-init 24) gives a rate of 2400 bps. (serial-init 10000) gives a 12 | ;; rate of 1 Mbps, which is the maximum. A common 'default' rate is 9600 bps: 13 | 14 | (serial-init 96) 15 | 16 | ;; (serial-write val) 17 | ;; Writes the given value to the serial port. Only 1 byte is sent, so data types other 18 | ;; than characters will be truncated. 19 | ;; This can be combined with the higher-order-function 'for-each-vector' in order to 20 | ;; print a string to the serial port: 21 | 22 | (for-each-vector serial-write "Hello Serial World!") 23 | 24 | ;; (serial-available) 25 | ;; Returns #t if any bytes are waiting in the serial RX buffer. 26 | 27 | ;; (serial-read) 28 | ;; Returns 1 byte from the RX buffer. Note that this procedure will block indefinitely until 29 | ;; a byte is recieved. We can use (serial-available) to check (poll) for incoming bytes, 30 | ;; without 'locking up' the program. 31 | 32 | ;; The following example sets up a simple 'echo' system: 33 | 34 | (define (polling-loop) 35 | (if (serial-available) 36 | (serial-write (serial-read))) 37 | (polling-loop)) 38 | 39 | (polling-loop) 40 | -------------------------------------------------------------------------------- /ffi_stuff/dump.py: -------------------------------------------------------------------------------- 1 | ## ======================= Microscheme ======================= 2 | ## Microscheme-C FFI demo 3 | ## (C) 2021 Ryan Suchocki, et al. 4 | ## http://github.com/ryansuchocki/microscheme 5 | ## 6 | 7 | import serial 8 | import time 9 | import sys 10 | 11 | 12 | ser = serial.Serial(sys.argv[1], 9600) 13 | ser.flushInput() 14 | ser.close() 15 | 16 | ser.open() 17 | 18 | b1 = 0 19 | b2 = 0 20 | val = 0 21 | 22 | ser.write(b'5') 23 | 24 | while 1: 25 | b1 = ser.read() 26 | print (str(b1)) 27 | -------------------------------------------------------------------------------- /ffi_stuff/ffi-test.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Microscheme-C FFI demo 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | ;; README: 8 | ;; To run this test, use the -w option to compile this file *with* 9 | ;; the C source file. 10 | ;; 11 | ;; $ microscheme -m ... -d ... -au -w ffi_stuff/ffitest.c ffi_stuff/ffi-test.ms 12 | 13 | ;; Define a scheme wrapper around each of our external functions... 14 | (define (pow x y) 15 | (call-c-func "mathpow" x y)) 16 | 17 | (define (vectsum x) 18 | (call-c-func "vectsum" x)) 19 | 20 | (define (listsum x) 21 | (call-c-func "listsum" x)) 22 | 23 | ;; We call each external C function, and send the result via Serial 24 | (serial-send (pow 6 4)) 25 | (serial-send (vectsum (vector 2 3 5 6))) 26 | (serial-send (listsum (list 2 3 5 6))) 27 | -------------------------------------------------------------------------------- /ffi_stuff/ffitest.c: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Microscheme-C FFI demo 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #include "microscheme_types.c" 8 | 9 | #include 10 | 11 | ms_value mathpow(ms_value x, ms_value y) 12 | { 13 | return round(pow(x, y)); 14 | } 15 | 16 | ms_value vectsum(ms_value v) 17 | { 18 | vector *vect = asVector(v); 19 | 20 | int i, total = 0; 21 | for (i = 0; i < vect->length; i++) 22 | { 23 | total += vect->data[i]; 24 | } 25 | 26 | return total; 27 | } 28 | 29 | ms_value listsum(ms_value v) 30 | { 31 | if (isNull(v)) return 0; 32 | 33 | pair *lst = asPair(v); 34 | 35 | return lst->car + listsum(lst->cdr); 36 | } -------------------------------------------------------------------------------- /ffi_stuff/microscheme_types.c: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Microscheme-C FFI library 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | struct vector; 11 | struct pair; 12 | struct closure; 13 | 14 | typedef unsigned int ms_value; 15 | 16 | typedef struct pair 17 | { 18 | ms_value car; 19 | ms_value cdr; 20 | } pair; 21 | 22 | typedef struct vector 23 | { 24 | unsigned int length; 25 | ms_value data[]; 26 | } vector; 27 | 28 | typedef struct closure 29 | { 30 | unsigned char arity; 31 | unsigned int entry; 32 | struct closure *chain; 33 | ms_value cells[]; 34 | } closure; 35 | 36 | pair *asPair(ms_value x) 37 | { 38 | return (pair *)(unsigned int)(x & 0b0001111111111111); 39 | } 40 | 41 | vector *asVector(ms_value x) 42 | { 43 | return (vector *)(unsigned int)(x & 0b0001111111111111); 44 | } 45 | 46 | closure *asClosure(ms_value x) 47 | { 48 | return (closure *)(unsigned int)(x & 0b0001111111111111); 49 | } 50 | 51 | unsigned char asChar(ms_value x) 52 | { 53 | return x & 0x00FF; 54 | } 55 | 56 | bool asBool(ms_value x) 57 | { 58 | return (x >> 8) & 0b00000001; 59 | } 60 | 61 | bool isNull(ms_value x) 62 | { 63 | return ((x >> 8) & 0b11111000) == 0b11101000; 64 | } 65 | 66 | ms_value ms_null = 0b1110100000000000; 67 | ms_value ms_true = 0b1111100100000000; 68 | ms_value ms_false = 0b1111100000000000; 69 | 70 | ms_value toChar(unsigned char x) 71 | { 72 | return 0b1110000000000000 | x; 73 | } 74 | 75 | ms_value toPair(pair *x) 76 | { 77 | return 0b1000000000000000 | (0b0001111111111111 & ((unsigned int)x)); 78 | } 79 | 80 | ms_value toVector(vector *x) 81 | { 82 | return 0b1010000000000000 | (0b0001111111111111 & ((unsigned int)x)); 83 | } 84 | 85 | ms_value toClosure(closure *x) 86 | { 87 | return 0b1100000000000000 | (0b0001111111111111 & ((unsigned int)x)); 88 | } 89 | 90 | ms_value cons(ms_value x, ms_value y) 91 | { 92 | pair *newcell = malloc(4); 93 | newcell->car = x; 94 | newcell->cdr = y; 95 | return toPair(newcell); 96 | } 97 | 98 | ms_value make_vector(unsigned int len) 99 | { 100 | vector *newvect = malloc(2 + len + len); 101 | newvect->length = len; 102 | return toVector(newvect); 103 | } 104 | -------------------------------------------------------------------------------- /libraries/ascii.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; ASCII library 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (define zerocode (char->number #\0)) 8 | 9 | (define (number->ascii n) 10 | (vector 11 | (+ (mod (div n 10000) 10) zerocode) 12 | (+ (mod (div n 1000) 10) zerocode) 13 | (+ (mod (div n 100) 10) zerocode) 14 | (+ (mod (div n 10) 10) zerocode) 15 | (+ (mod n 10) 48))) 16 | 17 | (define (long->ascii ln) 18 | (vector 19 | (+ (mod (div (car ln) 1000) 10) zerocode) 20 | (+ (mod (div (car ln) 100) 10) zerocode) 21 | (+ (mod (div (car ln) 10) 10) zerocode) 22 | (+ (mod (car ln) 10) zerocode) 23 | (+ (mod (div (cdr ln) 1000) 10) zerocode) 24 | (+ (mod (div (cdr ln) 100) 10) zerocode) 25 | (+ (mod (div (cdr ln) 10) 10) zerocode) 26 | (+ (mod (cdr ln) 10) zerocode))) 27 | 28 | (define (charzero? x) 29 | (= x zerocode)) 30 | 31 | (define (charnotzero? x) 32 | (not (= x zerocode))) 33 | 34 | (define (trim-leading-zeros vect) 35 | (sub-vector vect (vector-first vect charnotzero?) (- (vector-length vect) 1))) -------------------------------------------------------------------------------- /libraries/lcd.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; LCD Library 3 | ;; (C) 2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | (include "libraries/ascii.ms") 8 | 9 | (define lcdpins (vector 4 5 6 7 8 9)) 10 | ;; lcdpins: d0 d1 d2 d3 rs en 11 | 12 | (define (pulse) 13 | (set-pin (vector-ref lcdpins 5) #f) 14 | (micropause 1) 15 | (set-pin (vector-ref lcdpins 5) #t) 16 | (micropause 1) 17 | (set-pin (vector-ref lcdpins 5) #f) 18 | (micropause 1)) 19 | 20 | (define (write4bits val) 21 | (set-pin (vector-ref lcdpins 0) (not (zero? (mod val 2)))) 22 | (set-pin (vector-ref lcdpins 1) (not (zero? (mod (div val 2) 2)))) 23 | (set-pin (vector-ref lcdpins 2) (not (zero? (mod (div val 4) 2)))) 24 | (set-pin (vector-ref lcdpins 3) (not (zero? (mod (div val 8) 2)))) 25 | (pulse)) 26 | 27 | (define (send val mode) 28 | (set-pin (vector-ref lcdpins 4) mode) 29 | (write4bits (div val 16)) 30 | (write4bits val)) 31 | 32 | (define (lcd-init) 33 | (for-each-vector (lambda (pin) (set-ddr pin #t)) lcdpins) 34 | (pause 50) 35 | (set-pin (vector-ref lcdpins 4) #f) 36 | (set-pin (vector-ref lcdpins 5) #f) 37 | (write4bits 3) 38 | (pause 5) 39 | (write4bits 3) 40 | (pause 5) 41 | (write4bits 3) 42 | (pause 5) 43 | (write4bits 2) 44 | (send 40 #f) 45 | (send 12 #f) 46 | (send 1 #f) 47 | (pause 2) 48 | (send 6 #f) 49 | (send 128 #f)) 50 | 51 | (define (write val) 52 | (send (if (char? val) (char->number val) val) #t)) 53 | 54 | (define (set-cursor row col) 55 | (send (+ 128 (+ col (* 64 row))) #f)) 56 | 57 | (define (clear) 58 | (send 1 #f) 59 | (micropause 2000)) 60 | 61 | (define (writenum val) 62 | (free! 63 | (for-each-vector write (trim-leading-zeros (number->ascii val))))) 64 | 65 | (define (writestring str) 66 | (for-each-vector write str)) 67 | 68 | 69 | ;; Now we define a polymorphic structural 'print' function 70 | (define print) 71 | 72 | (define (print-list-step lst delimit) 73 | (write delimit) 74 | (print (car lst)) 75 | (if (null? (cdr lst)) 76 | (write #\rparen) 77 | (print-list-step (cdr lst) #\space))) 78 | 79 | (define (print-vector vect) 80 | (free! 81 | (write #\[) 82 | (print (vector-ref vect 0)) 83 | (for 1 (- (vector-length vect) 1) (lambda (i) 84 | (write #\|) 85 | (print (vector-ref vect i)))) 86 | (write #\]))) 87 | 88 | (define print (lambda (x) 89 | (if (number? x) (writenum x)) 90 | (if (boolean? x) (writestring (if x "#t" "#f"))) 91 | (if (char? x) (write x)) 92 | (if (list? x) (print-list-step x #\lparen) 93 | (if (pair? x) (begin (write #\<) (print (car x)) (write #\space) (print (cdr x)) (write #\>)))) 94 | (if (null? x) (writestring "()")) 95 | (if (string? x) (writestring x) 96 | (if (vector? x) (print-vector x))) 97 | (if (procedure? x) (begin (writestring "@p") (writenum (arity x)))))) 98 | 99 | 100 | 101 | ;; numbers, booleans and chars are printed directly. 102 | ;; Strings are printed directly, other Vectors are printed as [1|2|3] 103 | ;; Lists are printed as (1 2 3), other Pairs are printed as 104 | ;; Procedures are printed as @pr -------------------------------------------------------------------------------- /libraries/max7.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Library for MAX7219/MAX7221 chips 3 | ;; (C) 2014-2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | ;; These are serially-interfaced 8x8 multiplex drivers, commonly 8 | ;; used for LED arrays and 7-segment displays. 9 | 10 | ;; ==================== Internal procedures ==================== 11 | ;; (These should not be called directly) 12 | 13 | (define (shift-out-bits data-pin clock-pin data n) 14 | (set-pin data-pin (¬ (number? data))) 15 | (low (high clock-pin)) 16 | (or (zero? n) 17 | (shift-out-bits data-pin clock-pin (<< data) (- n 1)))) 18 | 19 | (define (noops data-pin clock-pin n) 20 | (or (zero? n) 21 | (begin 22 | (shift-out-bits data-pin clock-pin #x0000 15) 23 | (noops data-pin clock-pin (- n 1))))) 24 | 25 | (define (shift-out chip index data) 26 | (let ((data-pin (vector-ref chip 0)) 27 | (clock-pin (vector-ref chip 1)) 28 | (latch-pin (vector-ref chip 2)) 29 | (num (vector-ref chip 3))) 30 | (low latch-pin) 31 | (noops data-pin clock-pin (- (- num index) 1)) 32 | (shift-out-bits data-pin clock-pin data 15) 33 | (noops data-pin clock-pin index) 34 | (high latch-pin))) 35 | 36 | ;; ==================== External procedures ==================== 37 | ;; (These should be called directly) 38 | 39 | ;; Each chip features one data-in pin and one data-out pin, so that 40 | ;; up to 8 chips can be cascaded together, sharing a single data line. 41 | ;; Each cascade of chips must be initialised using def-max7. The result 42 | ;; is an object used to reference a particular cascade of chips, when it 43 | ;; comes to sending data. 44 | 45 | (define (def-max7 data-pin clock-pin latch-pin num) 46 | (vector 47 | (low (output data-pin)) 48 | (low (output clock-pin)) 49 | (high (output latch-pin)) 50 | num)) 51 | 52 | (define (digit chip index dig val) (shift-out chip index (+ (* dig #x100) val))) 53 | (define (decode chip index m) (shift-out chip index (+ #x0900 m))) 54 | (define (intensity chip index x) (shift-out chip index (+ #x0A00 x))) 55 | (define (scan-limit chip index n) (shift-out chip index (+ #x0B00 n))) 56 | (define (show chip index state) (shift-out chip index (if state #x0C01 #x0C00))) 57 | (define (test chip index state) (shift-out chip index (if state #x0F01 #x0F00))) 58 | 59 | 60 | ;; ======================= Example Usage ======================= 61 | 62 | ; (include "libraries/max7.ms") 63 | 64 | ; We have 2 max7219 chips cascaded together, on pins 10, 11 and 12 65 | ; (define led (def-max7 10 11 12 2)) 66 | ; ... connected to a 16-digit 7-segment display! 67 | 68 | ; We set both chips to decode-mode on all digits: 69 | ; So that we can send numeric characters directly (in BCD) 70 | ; (decode led 0 #xFF) 71 | ; (decode led 1 #xFF) 72 | 73 | ; Set the intensity to maximum on both chips: 74 | ; (intensity led 0 #x0F) 75 | ; (intensity led 1 #x0F) 76 | 77 | ; Enable all digits on both chips: 78 | ; (scan-limit led 0 #x07) 79 | ; (scan-limit led 1 #x07) 80 | 81 | ; Make sure both chips are out of 'shutdown' mode: 82 | ; (show led 0 #t) 83 | ; (show led 1 #t) 84 | 85 | ; Now we display the number '0102030405060708' 86 | 87 | ; (digit led 0 1 0) 88 | ; (digit led 0 2 1) 89 | ; (digit led 0 3 0) 90 | ; (digit led 0 4 2) 91 | ; (digit led 0 5 0) 92 | ; (digit led 0 6 3) 93 | ; (digit led 0 7 0) 94 | ; (digit led 0 8 4) 95 | ; (digit led 1 1 0) 96 | ; (digit led 1 2 5) 97 | ; (digit led 1 3 0) 98 | ; (digit led 1 4 6) 99 | ; (digit led 1 5 0) 100 | ; (digit led 1 6 7) 101 | ; (digit led 1 7 0) 102 | ; (digit led 1 8 8) 103 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | ## ======================= Microscheme ======================= 2 | ## Makefile 3 | ## (C) 2021 Ryan Suchocki, et al. 4 | ## http://github.com/ryansuchocki/microscheme 5 | ## 6 | 7 | PREFIX?=/usr/local 8 | 9 | all: check build 10 | hexify: src/assembly_hex.c src/microscheme_hex.c 11 | build: microscheme 12 | 13 | src/assembly_hex.c: src/*.s 14 | echo "// Hexified internal microscheme files." > src/assembly_hex.c 15 | xxd -i src/preamble.s >> src/assembly_hex.c 16 | 17 | src/microscheme_hex.c: src/*.ms 18 | echo "// Hexified internal microscheme files." > src/microscheme_hex.c 19 | xxd -i src/primitives.ms >> src/microscheme_hex.c 20 | xxd -i src/stdlib.ms >> src/microscheme_hex.c 21 | xxd -i src/avr_core.ms >> src/microscheme_hex.c 22 | 23 | microscheme: hexify src/*.h src/*.c 24 | gcc -ggdb -std=gnu99 -Wall -Wextra -Werror -o microscheme src/*.c 25 | 26 | check: 27 | cppcheck --enable=all --inconclusive --std=c11 --error-exitcode=2 src 28 | find src -type f -name '*.[c|h]' ! -name '*_hex.c' | xargs clang-format --dry-run --verbose --style=file 29 | 30 | format: 31 | find src -type f -name '*.[c|h]' ! -name '*_hex.c' | xargs clang-format -i --verbose --style=file 32 | 33 | install: 34 | install -d $(PREFIX)/bin/ 35 | install -m755 ./microscheme $(PREFIX)/bin/microscheme 36 | install -d $(PREFIX)/share/microscheme/ 37 | cp -r examples/ $(PREFIX)/share/microscheme/ 38 | 39 | clean: 40 | -rm microscheme 41 | -rm src/*.o 42 | -rm src/assembly_hex.c 43 | -rm src/microscheme_hex.c 44 | -------------------------------------------------------------------------------- /src/assembly_hex.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Header for hexified internal assembly source files 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _ASHEXIFIED_H_GUARD 8 | #define _ASHEXIFIED_H_GUARD 9 | 10 | extern unsigned char src_preamble_s[]; 11 | extern unsigned int src_preamble_s_len; 12 | 13 | extern unsigned char src_MEGA_s[]; 14 | extern unsigned int src_MEGA_s_len; 15 | 16 | extern unsigned char src_UNO_s[]; 17 | extern unsigned int src_UNO_s_len; 18 | 19 | extern unsigned char src_LEO_s[]; 20 | extern unsigned int src_LEO_s_len; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/codegen.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Code Generator 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _CODEGEN_H_GUARD 8 | #define _CODEGEN_H_GUARD 9 | 10 | #include "models.h" 11 | #include "parser.h" 12 | 13 | // Shared function declarations 14 | 15 | extern void codegen_emit(AST_expr *expr, int parent_numArgs, FILE *outputFile); 16 | extern void codegen_emitPreamble(FILE *outputFile /*, int numUsedGlobals*/); 17 | extern void codegen_emitPostamble(FILE *outputFile); 18 | extern void codegen_emitModelHeader(model_info theModel, FILE *outputFile); 19 | 20 | #endif -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Common helper module 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | void *tmp = 0; 12 | 13 | void *try_malloc(size_t size) 14 | { 15 | tmp = malloc(size); 16 | if (!tmp) 17 | { 18 | fprintf(stderr, "ERROR 0: Out of memory (malloc)\n"); 19 | exit(1); 20 | } 21 | return tmp; 22 | } 23 | 24 | void *try_realloc(void *ptr, size_t size) 25 | { 26 | tmp = realloc(ptr, size); 27 | if (!tmp) 28 | { 29 | fprintf(stderr, "ERROR 0: Out of memory (realloc)\n"); 30 | exit(1); 31 | } 32 | return tmp; 33 | } 34 | 35 | void try_free(void *ptr) 36 | { 37 | if (ptr) free(ptr); 38 | } 39 | 40 | char *str_clone(char *src) 41 | { 42 | char *new = try_malloc(sizeof(char) * (strlen(src) + 1)); 43 | return strcpy(new, src); 44 | } 45 | 46 | char *str_clone_more(char *src, int more) 47 | { 48 | char *new = try_malloc(sizeof(char) * (strlen(src) + 1 + more)); 49 | return strcpy(new, src); 50 | } -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Common helper module 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _COMMON_H_GUARD 8 | #define _COMMON_H_GUARD 9 | 10 | #include 11 | 12 | #define eprintf(...) fprintf(stderr, __VA_ARGS__) 13 | 14 | // Shared function declarations 15 | extern void *try_malloc(size_t size) __attribute__((returns_nonnull)); 16 | 17 | extern void *try_realloc(void *ptr, size_t size) __attribute__((returns_nonnull)); 18 | 19 | extern void try_free(void *ptr); 20 | extern char *str_clone(char *src); 21 | extern char *str_clone_more(char *src, int more); 22 | 23 | #endif -------------------------------------------------------------------------------- /src/lexer.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Lexical Analyser 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _LEXER_H_GUARD 8 | #define _LEXER_H_GUARD 9 | 10 | // Type definitions 11 | enum lexer_tokenNodeType 12 | { 13 | Keyword, 14 | Primword, 15 | Numerictoken, 16 | Identifier, 17 | Stringtoken, 18 | Booleantoken, 19 | Chartoken, 20 | Parens, 21 | Nulltoken 22 | }; 23 | enum keywordtype 24 | { 25 | lambda, 26 | ifword, 27 | when, 28 | let, 29 | set, 30 | define, 31 | begin, 32 | andword, 33 | orword, 34 | includeword, 35 | freeword, 36 | ifmodelword, 37 | listword, 38 | vectorword, 39 | callcfuncword, 40 | includeasmword, 41 | asmword 42 | }; 43 | typedef struct lexer_tokenNode 44 | { 45 | enum lexer_tokenNodeType type; 46 | enum keywordtype keyword; 47 | char *raw; 48 | struct lexer_tokenNode **children; 49 | int numChildren; 50 | struct lexer_tokenNode *parent; 51 | int fileLine; 52 | } lexer_tokenNode; 53 | 54 | // Shared variable declarations 55 | // extern lexer_tokenNode *lexer_openNode; 56 | extern int fileLine; 57 | 58 | // Shared function declarations 59 | extern void lexer_lex(char ch); 60 | extern void lexer_freeTokenTree(lexer_tokenNode *tree); 61 | extern lexer_tokenNode *lexer_lexFile(char *filename, lexer_tokenNode *root); 62 | extern lexer_tokenNode *lexer_lexBlob(unsigned char *blob, unsigned int length, lexer_tokenNode *root); 63 | 64 | #endif -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Main Program 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _MAIN_H_GUARD 8 | #define _MAIN_H_GUARD 9 | 10 | extern int opt_includeonce; 11 | 12 | #endif -------------------------------------------------------------------------------- /src/microscheme_hex.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Header for hexified internal microscheme source files 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _MSHEXIFIED_H_GUARD 8 | #define _MSHEXIFIED_H_GUARD 9 | 10 | extern unsigned char src_primitives_ms[]; 11 | extern unsigned int src_primitives_ms_len; 12 | 13 | extern unsigned char src_stdlib_ms[]; 14 | extern unsigned int src_stdlib_ms_len; 15 | 16 | extern unsigned char src_avr_core_ms[]; 17 | extern unsigned int src_avr_core_ms_len; 18 | 19 | #endif -------------------------------------------------------------------------------- /src/models.c: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Definitions for specific hardware models 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #include "models.h" 8 | 9 | #include 10 | 11 | model_info models[] = { 12 | {"MEGA", 13 | 14 | "atmega2560", 15 | "wiring", 16 | "115200", 17 | 18 | false, 19 | 20 | ".EQU PORT13, 0x05 \n" 21 | ".EQU DDR13, 0x04 \n" 22 | ".EQU P13, 7 \n" 23 | 24 | // This is necessary to stay within 13-bit addresses! 25 | ".EQU _ms_stack, 0x2000\n" 26 | 27 | ".EQU UDR0, 0xC6 \n" 28 | ".EQU UBRR0H, 0xC5 \n" 29 | ".EQU UBRR0L, 0xC4 \n" 30 | ".EQU UCSR0C, 0xC2 \n" 31 | ".EQU UCSR0B, 0xC1 \n" 32 | ".EQU UCSR0A, 0xC0 \n" 33 | ".EQU TXEN0, 3 \n" 34 | ".EQU RXEN0, 4 \n" 35 | ".EQU UDRE0, 5 \n" 36 | ".EQU TXC0, 6 \n" 37 | ".EQU RXC0, 7 \n" 38 | ".EQU BAUD_9600, 103 \n" 39 | 40 | ".EQU ADMUX, 0x7C \n" 41 | ".EQU ADCSRA, 0x7A \n" 42 | ".EQU ADCH, 0x79 \n" 43 | ".EQU ADCL, 0x78 \n" 44 | ".EQU REFS0, 6 \n" 45 | ".EQU ADSC, 6 \n"}, 46 | {"UNO", 47 | 48 | "atmega328p", 49 | "arduino", 50 | "115200", 51 | 52 | false, 53 | 54 | ".EQU PORT13, 0x05 \n" 55 | ".EQU DDR13, 0x04 \n" 56 | ".EQU P13, 5 \n" 57 | 58 | ".EQU _ms_stack, __stack\n" 59 | 60 | ".EQU UDR0, 0xC6 \n" 61 | ".EQU UBRR0H, 0xC5 \n" 62 | ".EQU UBRR0L, 0xC4 \n" 63 | ".EQU UCSR0C, 0xC2 \n" 64 | ".EQU UCSR0B, 0xC1 \n" 65 | ".EQU UCSR0A, 0xC0 \n" 66 | ".EQU TXEN0, 3 \n" 67 | ".EQU RXEN0, 4 \n" 68 | ".EQU UDRE0, 5 \n" 69 | ".EQU TXC0, 6 \n" 70 | ".EQU RXC0, 7 \n" 71 | ".EQU BAUD_9600, 103 \n" 72 | 73 | ".EQU ADMUX, 0x7C \n" 74 | ".EQU ADCSRA, 0x7A \n" 75 | ".EQU ADCH, 0x79 \n" 76 | ".EQU ADCL, 0x78 \n" 77 | ".EQU REFS0, 6 \n" 78 | ".EQU ADSC, 6 \n"}, 79 | {"LEO", 80 | 81 | "atmega32u4", 82 | "avr109", 83 | "57600", 84 | 85 | true, 86 | 87 | ".EQU PORT13, 0x08 \n" 88 | ".EQU DDR13, 0x07 \n" 89 | ".EQU P13, 7 \n" 90 | 91 | ".EQU _ms_stack, __stack\n" 92 | 93 | ".EQU ADMUX, 0x7C \n" 94 | ".EQU ADCSRA, 0x7A \n" 95 | ".EQU ADCH, 0x79 \n" 96 | ".EQU ADCL, 0x78 \n" 97 | ".EQU REFS0, 6 \n" 98 | ".EQU ADSC, 6 \n"}}; 99 | 100 | int numModels = sizeof(models) / sizeof(model_info); 101 | -------------------------------------------------------------------------------- /src/models.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Definitions for specific hardware models 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _MODELS_H_GUARD 8 | #define _MODELS_H_GUARD 9 | 10 | #include 11 | 12 | typedef struct model_info 13 | { 14 | char *name; 15 | 16 | char *STR_TARGET; 17 | char *STR_PROG; 18 | char *STR_BAUD; 19 | 20 | bool software_reset; 21 | 22 | char *specific_asm; 23 | } model_info; 24 | 25 | extern model_info models[]; 26 | extern int numModels; 27 | 28 | #endif -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Parser 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _PARSER_H_GUARD 8 | #define _PARSER_H_GUARD 9 | 10 | #include "lexer.h" 11 | 12 | #include 13 | 14 | // Type definitions 15 | enum AST_constType 16 | { 17 | Booleanconst, 18 | Charconst, 19 | Stringconst, 20 | Numconst, 21 | Emptylistconst 22 | }; 23 | typedef struct AST_const 24 | { 25 | enum AST_constType type; 26 | int value; 27 | char *strvalue; 28 | } AST_const; 29 | enum AST_exprType 30 | { 31 | Constant, 32 | Variable, 33 | Lambda, 34 | Branch, 35 | When, 36 | Definition, 37 | Assignment, 38 | Sequence, 39 | ProcCall, 40 | And, 41 | Or, 42 | PrimCall, 43 | TailCall, 44 | OtherFundemental 45 | }; 46 | enum AST_varRefType 47 | { 48 | Local, 49 | Free, 50 | Global 51 | }; 52 | typedef struct AST_expr 53 | { 54 | enum AST_exprType type; 55 | struct AST_const *value; 56 | char *variable; 57 | char **formal; 58 | int numFormals; 59 | struct AST_expr **body; 60 | int numBody; 61 | char *primproc; 62 | struct AST_expr *proc; 63 | enum AST_varRefType varRefType; 64 | int varRefHop; 65 | int varRefIndex; 66 | struct Environment *closure; 67 | bool stack_allocate; 68 | } AST_expr; 69 | 70 | // Shared function declarations 71 | extern AST_expr *parser_parseExpr(lexer_tokenNode **token, int numTokens, bool topLevel, bool tailPosition); 72 | extern AST_expr *parser_parseFile(lexer_tokenNode **token, int numTokens); 73 | extern void parser_freeAST(AST_expr *tree); 74 | extern void parser_initExpr(AST_expr *expr); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/preamble.s: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Runtime startup code for AVR 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | .text 8 | .global main 9 | main: 10 | 11 | .EQU MLX1, 0 ; Hardware Multiplier 12 | .EQU MLX2, 1 ; Hardware Multiplier 13 | .EQU TCSl, 2 ; Tail Call Special/Save 14 | .EQU TCSh, 3 ; Tail Call Special/Save 15 | .EQU falseReg, 4 16 | .EQU zeroReg, 5 17 | .EQU c_sreg, 6 18 | ; 7 19 | 20 | ; 8 21 | ; 9 22 | ; 10 23 | ; 11 24 | ; 12 25 | ; 13 26 | ; 14 27 | ; 15 28 | 29 | .EQU GP1, 16 ; General Purpose 1 (used by multiplication) 30 | .EQU GP2, 17 ; General Purpose 2 (used by multiplication) 31 | .EQU GP3, 18 ; General Purpose 3 (used by multiplication) 32 | .EQU GP4, 19 ; General Purpose 4 (used by multiplication) 33 | .EQU GP5, 20 ; General Purpose 5 34 | .EQU GP6, 21 ; General Purpose 6 35 | ; 22 36 | .EQU PCR, 23 ; proc call register 37 | 38 | 39 | .EQU CCPl, 24 40 | .EQU CCPh, 25 41 | .EQU HFPl, 26 42 | .EQU HFPh, 27 43 | .EQU CRSl, 28 44 | .EQU CRSh, 29 45 | .EQU AFPl, 30 46 | .EQU AFPh, 31 47 | 48 | .EQU SREG, 0x3F 49 | 50 | .EQU falseHigh, 254 51 | .EQU trueHigh, 255 52 | 53 | ;; 16-bit counting registers, of which XYZ are 54 | ;; are memory address registers. 55 | .EQU WL, 0x18 56 | .EQU WH, 0x19 57 | .EQU XL, 0x1A 58 | .EQU XH, 0x1B 59 | .EQU YL, 0x1C 60 | .EQU YH, 0x1D 61 | .EQU ZL, 0x1E 62 | .EQU ZH, 0x1F 63 | 64 | .EQU SPl, 0x3D 65 | .EQU SPh, 0x3E 66 | 67 | LDI GP1, falseHigh 68 | MOV falseReg, GP1 69 | CLR zeroReg 70 | 71 | CLI 72 | IN c_sreg, SREG 73 | 74 | LDI CRSl, 0 75 | LDI CRSh, 0 76 | LDI HFPl, lo8(_end) 77 | LDI HFPh, hi8(_end) 78 | LDI CCPl, 0 79 | LDI CCPh, 0 80 | LDI AFPl, lo8(_ms_stack) 81 | LDI AFPh, hi8(_ms_stack) 82 | 83 | OUT SPl, AFPl 84 | OUT SPh, AFPh 85 | 86 | SBI DDR13, P13 87 | CBI PORT13, P13 88 | 89 | RJMP entry_point 90 | 91 | proc_call: 92 | MOV GP1, CRSh 93 | ANDI GP1, 224 94 | LDI GP2, 192 95 | CPSE GP1, GP2 96 | RJMP error_notproc 97 | ANDI CRSh, 31 98 | MOVW CCPl, CRSl 99 | LD GP1, Y;CRS 100 | CPSE GP1, PCR 101 | RJMP error_numargs 102 | LDD AFPh, Y+1;CRS 103 | LDD AFPl, Y+2;CRS 104 | IJMP 105 | 106 | before_c_func: 107 | POP r2 108 | POP r3 109 | PUSH CCPl 110 | PUSH CCPh 111 | PUSH HFPl 112 | PUSH HFPh 113 | PUSH AFPl 114 | PUSH AFPh 115 | PUSH r1 116 | CLR r1 117 | PUSH r3 118 | PUSH r2 119 | OUT SREG, c_sreg 120 | RET 121 | 122 | after_c_func: 123 | IN c_sreg, SREG 124 | CLI 125 | POP r2 126 | POP r3 127 | MOVW CRSl, r24 128 | POP r1 129 | POP AFPh 130 | POP AFPl 131 | POP HFPh 132 | POP HFPl 133 | POP CCPh 134 | POP CCPl 135 | PUSH r3 136 | PUSH r2 137 | RET 138 | 139 | inline_cons: 140 | ST X+, GP1;HFP 141 | ST X+, GP2 142 | ST X+, CRSl 143 | ST X+, CRSh 144 | MOVW CRSl, HFPl 145 | SBIW CRSl, 4 146 | ORI CRSh, 128 147 | RET 148 | 149 | inline_car: 150 | MOV GP1, CRSh 151 | ANDI GP1, 224 152 | LDI GP2, 128 153 | CPSE GP1, GP2 154 | RJMP error_notpair 155 | ANDI CRSh, 31 156 | LDD GP1, Y+0; (Y=CRS) 157 | LDD CRSh, Y+1 158 | MOV CRSl, GP1 159 | RET 160 | 161 | inline_cdr: 162 | MOV GP1, CRSh 163 | ANDI GP1, 224 164 | LDI GP2, 128 165 | CPSE GP1, GP2 166 | RJMP error_notpair 167 | ANDI CRSh, 31 168 | LDD GP1, Y+2; (Y=CRS) 169 | LDD CRSh, Y+3 170 | MOV CRSl, GP1 171 | RET 172 | 173 | inline_set_car: 174 | MOV GP3, CRSh 175 | ANDI GP3, 224 176 | LDI GP4, 128 177 | CPSE GP3, GP4 178 | RJMP error_notpair 179 | ANDI CRSh, 31 180 | STD Y+0, GP1 181 | STD Y+1, GP2 182 | RET 183 | 184 | inline_set_cdr: 185 | MOV GP3, CRSh 186 | ANDI GP3, 224 187 | LDI GP4, 128 188 | CPSE GP3, GP4 189 | RJMP error_notpair 190 | ANDI CRSh, 31 191 | STD Y+2, GP1 192 | STD Y+3, GP2 193 | RET 194 | 195 | inline_vector_ref: 196 | MOV GP3, CRSh 197 | ANDI GP3, 224 198 | LDI GP4, 160 199 | CPSE GP3, GP4 200 | RJMP error_notvect 201 | ANDI CRSh, 31 202 | LD GP3, Y+ 203 | LD GP4, Y+ 204 | CP GP1, GP3 205 | CPC GP2, GP4 206 | BRLO inline_vector_ref_ok 207 | RJMP error_bounds 208 | inline_vector_ref_ok: 209 | LSL GP1 210 | ROL GP2 211 | ADD CRSl, GP1 212 | ADC CRSh, GP2 213 | LD GP1, Y 214 | LDD CRSh, Y+1 215 | MOV CRSl, GP1 216 | RET 217 | 218 | inline_vector_set: 219 | MOV GP5, CRSh 220 | ANDI GP5, 224 221 | LDI GP6, 160 222 | CPSE GP5, GP6 223 | RJMP error_notvect 224 | ANDI CRSh, 31 225 | LD GP5, Y+ 226 | LD GP6, Y+ 227 | CP GP1, GP5 228 | CPC GP2, GP6 229 | BRLO inline_vector_set_ok 230 | RJMP error_bounds 231 | inline_vector_set_ok: 232 | LSL GP1 233 | ROL GP2 234 | ADD CRSl, GP1 235 | ADC CRSh, GP2 236 | ST Y, GP3 237 | STD Y+1, GP4 238 | RET 239 | 240 | inline_vector_length: 241 | MOV GP3, CRSh 242 | ANDI GP3, 224 243 | LDI GP4, 160 244 | CPSE GP3, GP4 245 | RJMP error_notvect 246 | ANDI CRSh, 31 247 | LD GP1, Y 248 | LDD CRSh, Y+1 249 | MOV CRSl, GP1 250 | RET 251 | 252 | inline_gt: ; GP1:GP2 > CRSl:CRSh 253 | CP CRSl, GP1 254 | CPC CRSh, GP2 255 | BRLO inline_gt_ok 256 | LDI CRSh, falseHigh 257 | CLR CRSl 258 | RET 259 | inline_gt_ok: 260 | LDI CRSh, trueHigh 261 | CLR CRSl 262 | RET 263 | 264 | inline_div: ; GP1:GP2 / CRSl:CRSh 265 | MOVW GP3, CRSl 266 | CLR CRSl 267 | CLR CRSh 268 | CP GP3, zeroReg 269 | CPC GP4, zeroReg 270 | BRNE inline_div_loop 271 | RJMP error_divzero 272 | inline_div_loop: 273 | SUB GP1, GP3 274 | SBC GP2, GP4 275 | BRLO inline_div_end 276 | ADIW CRSl, 1 277 | RJMP inline_div_loop 278 | inline_div_end: 279 | RET 280 | 281 | error_notproc: 282 | RCALL util_flash 283 | LDI YH, hi8(1000) 284 | LDI YL, lo8(1000) 285 | RCALL util_pause 286 | RJMP error_notproc 287 | 288 | error_numargs: 289 | RCALL util_flash 290 | RCALL util_flash 291 | LDI YH, hi8(1000) 292 | LDI HFPl, lo8(1000) 293 | RCALL util_pause 294 | RJMP error_numargs 295 | 296 | error_notnum: 297 | RCALL util_flash 298 | RCALL util_flash 299 | RCALL util_flash 300 | LDI YH, hi8(1000) 301 | LDI HFPl, lo8(1000) 302 | RCALL util_pause 303 | RJMP error_notnum 304 | 305 | error_notpair: 306 | RCALL util_flash 307 | RCALL util_flash 308 | RCALL util_flash 309 | RCALL util_flash 310 | LDI YH, hi8(1000) 311 | LDI HFPl, lo8(1000) 312 | RCALL util_pause 313 | RJMP error_notpair 314 | 315 | error_notvect: 316 | RCALL util_flash 317 | RCALL util_flash 318 | RCALL util_flash 319 | RCALL util_flash 320 | RCALL util_flash 321 | LDI YH, hi8(1000) 322 | LDI HFPl, lo8(1000) 323 | RCALL util_pause 324 | RJMP error_notvect 325 | 326 | error_bounds: 327 | RCALL util_flash 328 | RCALL util_flash 329 | RCALL util_flash 330 | RCALL util_flash 331 | RCALL util_flash 332 | RCALL util_flash 333 | LDI YH, hi8(1000) 334 | LDI HFPl, lo8(1000) 335 | RCALL util_pause 336 | RJMP error_bounds 337 | 338 | error_divzero: 339 | RCALL util_flash 340 | RCALL util_flash 341 | RCALL util_flash 342 | RCALL util_flash 343 | RCALL util_flash 344 | RCALL util_flash 345 | RCALL util_flash 346 | LDI YH, hi8(1000) 347 | LDI HFPl, lo8(1000) 348 | RCALL util_pause 349 | RJMP error_divzero 350 | 351 | error_custom: 352 | RCALL util_flash 353 | RJMP error_custom 354 | 355 | 356 | 357 | 358 | ; INPUT: Y = delay (milliseconds) 359 | util_pause: 360 | PUSH WH 361 | PUSH WL 362 | 363 | util_pause_count: 364 | LDI WH, hi8(0xFA0) 365 | LDI WL, lo8(0xFA0) 366 | util_pause_inner_count: 367 | SBIW WL, 1 368 | BRNE util_pause_inner_count 369 | SBIW YL, 1 370 | BRNE util_pause_count 371 | ;; NB: In total, this routine takes Y*16002 + 17 operations 372 | 373 | POP WL 374 | POP WH 375 | RET 376 | 377 | ; INPUT: Y = delay (microseconds) 378 | util_micropause: 379 | util_micropause_count: 380 | PUSH zeroReg 381 | POP zeroReg 382 | PUSH zeroReg 383 | POP zeroReg 384 | PUSH zeroReg 385 | POP zeroReg 386 | NOP 387 | SBIW YL, 1 388 | BRNE util_micropause_count 389 | RET 390 | 391 | util_flash: 392 | SBI PORT13, P13 393 | LDI YH, hi8(200) 394 | LDI YL, lo8(200) 395 | RCALL util_pause 396 | CBI PORT13, P13 397 | LDI YH, hi8(200) 398 | LDI YL, lo8(200) 399 | RCALL util_pause 400 | RET 401 | 402 | entry_point: 403 | -------------------------------------------------------------------------------- /src/primitives.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; Primitive Values Library 3 | ;; (C) 2014-2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | ;; Primitives 8 | 9 | (define (eq? x y) (eq? x y)) 10 | (define (= x y) (= x y)) 11 | (define (> x y) (> x y)) 12 | (define (>= x y) (>= x y)) 13 | (define (< x y) (< x y)) 14 | (define (<= x y) (<= x y)) 15 | (define (not x) (not x)) 16 | (define (¬ x) (¬ x)) 17 | 18 | (define (+ x y) (+ x y)) 19 | (define (* x y) (* x y)) 20 | (define (- x y) (- x y)) 21 | (define (div x y) (div x y)) 22 | (define (mod x y) (mod x y)) 23 | (define (zero? x) (zero? x)) 24 | 25 | (define (number? x) (number? x)) 26 | (define (pair? x) (pair? x)) 27 | (define (vector? x) (vector? x)) 28 | (define (procedure? x) (procedure? x)) 29 | (define (char? x) (char? x)) 30 | (define (boolean? x) (boolean? x)) 31 | (define (null? x) (null? x)) 32 | 33 | (define (cons x y) (cons x y)) 34 | (define (car x) (car x)) 35 | (define (cdr x) (cdr x)) 36 | (define (set-car! x y) (set-car! x y)) 37 | (define (set-cdr! x y) (set-cdr! x y)) 38 | 39 | (define (vector-length x) (vector-length x)) 40 | (define (vector-ref x y) (vector-ref x y)) 41 | (define (vector-set! x y z) (vector-set! x y z)) 42 | (define (make-vector x) (make-vector x)) 43 | 44 | (define (assert x) (assert x)) 45 | (define (error) (error)) 46 | (define (stacksize) (stacksize)) 47 | (define (heapsize) (heapsize)) 48 | (define (pause x) (pause x)) 49 | (define (micropause x) (micropause x)) 50 | 51 | (define (digital-state x y) (digital-state x y)) 52 | (define (set-digital-state x y z) (set-digital-state x y z)) 53 | (define (register-state x) (register-state x)) 54 | (define (set-register-state x y) (set-register-state x y)) 55 | (define (char->number x) (char->number x)) 56 | (define (number->char x) (number->char x)) 57 | (define (arity x) (arity x)) 58 | 59 | (define (>> x) (>> x)) 60 | (define (<< x) (<< x)) 61 | (define (| x y) (| x y)) 62 | (define (& x y) (& x y)) 63 | (define (~ x) (~ x)) 64 | (define (^ x y) (^ x y)) 65 | -------------------------------------------------------------------------------- /src/scoper.c: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Scope Analyser 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #include "scoper.h" 8 | 9 | #include "common.h" 10 | #include "lexer.h" 11 | #include "parser.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | Environment *currentEnvironment; 19 | Environment *currentClosureEnvironment; 20 | 21 | void scoper_initEnv(Environment *env) 22 | { 23 | env->binding = NULL; 24 | env->lexicalAddrV = NULL; 25 | env->lexicalAddrH = NULL; 26 | env->references = NULL; 27 | env->realAddress = NULL; 28 | env->numBinds = 0; 29 | env->enclosing = NULL; 30 | } 31 | 32 | int getBindingIndex(char *variable, Environment *env) 33 | { 34 | int i; 35 | for (i = 0; env && i < env->numBinds; i++) 36 | { 37 | if (strcmp(env->binding[i], variable) == 0) 38 | return i; 39 | } 40 | return -1; 41 | } 42 | 43 | AST_expr *scoper_scopeExpr(AST_expr *expr) 44 | { 45 | Environment *innerEnvironment, *tmpEnv, *tmpClosEnv, *last; 46 | 47 | int i, j, depth; 48 | 49 | switch (expr->type) 50 | { 51 | // The simple ones (recursion only): 52 | case Constant: 53 | return expr; 54 | case ProcCall: 55 | // fall through 56 | case TailCall: 57 | expr->proc = scoper_scopeExpr(expr->proc); 58 | // fall through 59 | case Branch: 60 | // fall through 61 | case When: 62 | // fall through 63 | case Sequence: 64 | // fall through 65 | case PrimCall: 66 | // fall through 67 | case OtherFundemental: 68 | // fall through 69 | case And: 70 | // fall through 71 | case Or: 72 | for (i = 0; i < expr->numBody; i++) 73 | { 74 | expr->body[i] = scoper_scopeExpr(expr->body[i]); 75 | } 76 | return expr; 77 | 78 | // Environment-altering expressions: 79 | case Definition: 80 | 81 | if (getBindingIndex(expr->variable, currentEnvironment) < 0) 82 | { 83 | if (currentEnvironment->numBinds == 0) 84 | { 85 | currentEnvironment->binding = (char **)try_malloc(sizeof(char *)); 86 | currentEnvironment->references = (int *)try_malloc(sizeof(int)); 87 | } 88 | else 89 | { 90 | currentEnvironment->binding = (char **)try_realloc(currentEnvironment->binding, sizeof(char *) * (currentEnvironment->numBinds + 1)); 91 | currentEnvironment->references = (int *)try_realloc(currentEnvironment->references, sizeof(int) * (currentEnvironment->numBinds + 1)); 92 | } 93 | 94 | currentEnvironment->binding[currentEnvironment->numBinds] = str_clone(expr->variable); 95 | currentEnvironment->references[currentEnvironment->numBinds] = 0; 96 | 97 | currentEnvironment->numBinds++; 98 | } 99 | 100 | if (expr->numBody == 1) 101 | { 102 | 103 | expr->type = Assignment; 104 | AST_expr *result = scoper_scopeExpr(expr); 105 | expr->type = Definition; 106 | 107 | return result; 108 | } 109 | else 110 | { 111 | return expr; 112 | } 113 | 114 | case Lambda: 115 | innerEnvironment = try_malloc(sizeof(Environment)); 116 | scoper_initEnv(innerEnvironment); 117 | innerEnvironment->enclosing = currentEnvironment; 118 | innerEnvironment->numBinds = expr->numFormals; 119 | 120 | innerEnvironment->binding = try_malloc(sizeof(char *) * expr->numFormals); 121 | for (i = 0; i < expr->numFormals; i++) 122 | { 123 | innerEnvironment->binding[i] = str_clone(expr->formal[i]); 124 | } 125 | 126 | innerEnvironment->references = try_malloc(sizeof(int) * expr->numFormals); 127 | for (i = 0; i < expr->numFormals; i++) 128 | { 129 | innerEnvironment->references[i] = 0; 130 | } 131 | 132 | // switch environments 133 | currentEnvironment = innerEnvironment; 134 | 135 | expr->closure = try_malloc(sizeof(Environment)); 136 | scoper_initEnv(expr->closure); 137 | expr->closure->enclosing = currentClosureEnvironment; 138 | 139 | currentClosureEnvironment = expr->closure; 140 | 141 | // scope the body 142 | for (i = 0; i < expr->numBody; i++) 143 | { 144 | expr->body[i] = scoper_scopeExpr(expr->body[i]); 145 | } 146 | 147 | // restore the environment 148 | currentEnvironment = innerEnvironment->enclosing; 149 | currentClosureEnvironment = currentClosureEnvironment->enclosing; 150 | freeEnvironment(innerEnvironment); 151 | 152 | return expr; 153 | 154 | // Environment-dependant expressions: 155 | case Assignment: 156 | expr->body[0] = scoper_scopeExpr(expr->body[0]); 157 | // fall through 158 | 159 | case Variable: 160 | tmpEnv = currentEnvironment; 161 | tmpClosEnv = currentClosureEnvironment; 162 | depth = 0; 163 | 164 | do 165 | { 166 | if ((i = getBindingIndex(expr->variable, tmpEnv)) >= 0) 167 | { 168 | 169 | //DEBUG printf("IN IMMEDIATE SCOPE %s\n", expr->variable); 170 | 171 | if (tmpEnv->enclosing == NULL) 172 | { 173 | expr->varRefType = Global; 174 | } 175 | else if (tmpEnv == currentEnvironment) 176 | { 177 | expr->varRefType = Local; 178 | } 179 | else 180 | { 181 | expr->varRefType = Free; 182 | expr->varRefHop = depth; 183 | 184 | tmpClosEnv = last; 185 | 186 | if ((j = getBindingIndex(expr->variable, tmpClosEnv)) < 0) 187 | { 188 | if (tmpClosEnv->numBinds == 0) 189 | { 190 | tmpClosEnv->binding = try_malloc(sizeof(char *)); 191 | tmpClosEnv->lexicalAddrV = try_malloc(sizeof(int)); 192 | tmpClosEnv->lexicalAddrH = try_malloc(sizeof(int)); 193 | } 194 | else 195 | { 196 | tmpClosEnv->binding = try_realloc(tmpClosEnv->binding, sizeof(char *) * (tmpClosEnv->numBinds + 1)); 197 | tmpClosEnv->lexicalAddrV = try_realloc(tmpClosEnv->lexicalAddrV, sizeof(int) * (tmpClosEnv->numBinds + 1)); 198 | tmpClosEnv->lexicalAddrH = try_realloc(tmpClosEnv->lexicalAddrH, sizeof(int) * (tmpClosEnv->numBinds + 1)); 199 | } 200 | 201 | //fprintf(stderr, ""); 202 | tmpClosEnv->binding[tmpClosEnv->numBinds] = str_clone(expr->variable); 203 | tmpClosEnv->lexicalAddrH[tmpClosEnv->numBinds] = i; 204 | tmpClosEnv->lexicalAddrV[tmpClosEnv->numBinds] = 1; 205 | 206 | j = tmpClosEnv->numBinds; 207 | tmpClosEnv->numBinds++; 208 | } 209 | 210 | expr->varRefIndex = j; 211 | 212 | //fprintf(stderr, "<%s is %ith in closure>\n", expr->variable, j); 213 | return expr; 214 | } 215 | 216 | expr->varRefIndex = i; 217 | 218 | return expr; 219 | } 220 | 221 | tmpEnv = tmpEnv->enclosing; 222 | last = tmpClosEnv; 223 | if (tmpClosEnv) 224 | tmpClosEnv = tmpClosEnv->enclosing; 225 | 226 | depth++; 227 | } while (tmpEnv); 228 | 229 | fprintf(stderr, "ERROR 23: NOT IN SCOPE %s\nCurrent Environment is: ", expr->variable); 230 | for (i = 0; i < currentEnvironment->numBinds; i++) 231 | fprintf(stderr, "[%s] ", currentEnvironment->binding[i]); 232 | fprintf(stderr, "\n"); 233 | exit(EXIT_FAILURE); 234 | 235 | return expr; 236 | 237 | default: 238 | //wtf!? 239 | fprintf(stderr, "INTERNAL ERROR @ SCOPER CASE"); 240 | exit(EXIT_FAILURE); 241 | } 242 | } 243 | 244 | void freeEnvironment(Environment *env) 245 | { 246 | 247 | int i = 0; 248 | 249 | for (i = 0; i < env->numBinds; i++) 250 | { 251 | try_free(env->binding[i]); 252 | } 253 | try_free(env->binding); 254 | try_free(env->lexicalAddrV); 255 | try_free(env->lexicalAddrH); 256 | try_free(env->references); 257 | try_free(env->realAddress); 258 | 259 | try_free(env); 260 | } 261 | -------------------------------------------------------------------------------- /src/scoper.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Scope Analyser 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _SCOPER_H_GUARD 8 | #define _SCOPER_H_GUARD 9 | 10 | #include "parser.h" 11 | 12 | // Type definitions 13 | typedef struct Environment 14 | { 15 | char **binding; 16 | int *lexicalAddrV; 17 | int *lexicalAddrH; 18 | int *references; 19 | int *realAddress; 20 | int numBinds; 21 | struct Environment *enclosing; 22 | } Environment; 23 | 24 | // Shared variable declarations 25 | extern Environment *currentEnvironment; 26 | extern Environment *currentClosureEnvironment; 27 | 28 | // Shared function declarations 29 | extern AST_expr *scoper_scopeExpr(AST_expr *expr); 30 | extern void freeEnvironment(Environment *env); 31 | extern void scoper_initEnv(Environment *env); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/stdlib.ms: -------------------------------------------------------------------------------- 1 | ;; ======================= Microscheme ======================= 2 | ;; The Standard Library 3 | ;; (C) 2014-2021 Ryan Suchocki, et al. 4 | ;; http://github.com/ryansuchocki/microscheme 5 | ;; 6 | 7 | 8 | ;; Looping constructs 9 | 10 | (define (forever f) 11 | (f) 12 | (forever f)) 13 | 14 | (define (vector-last vect) 15 | (- (vector-length vect) 1)) 16 | 17 | (define (for a z f) 18 | (if (<= a z) 19 | (begin 20 | (f a) 21 | (for (+ a 1) z f)))) 22 | 23 | ;; Rich equivalence predicate 24 | 25 | (define equal? #f) 26 | 27 | (define (vector-equal-aux test? X Y N L) 28 | (if (= N L) 29 | #t 30 | (if (test? (vector-ref X N) (vector-ref Y N)) 31 | (vector-equal-aux test? X Y (+ N 1) L) 32 | #f))) 33 | 34 | (define equal? (lambda (X Y) 35 | (or 36 | (eq? X Y) 37 | (and 38 | (pair? X) 39 | (pair? Y) 40 | (equal? (car X) (car Y)) 41 | (equal? (cdr X) (cdr Y))) 42 | (and 43 | (vector? X) 44 | (vector? Y) 45 | (= (vector-length X) (vector-length Y)) 46 | (vector-equal-aux equal? X Y 0 (vector-length X)))))) 47 | 48 | (define (all-vector-aux test X N L) 49 | (if (= N L) 50 | #t 51 | (if (test (vector-ref X N)) 52 | (all-vector-aux test X (+ N 1) L) 53 | #f))) 54 | 55 | (define (all-vector test vect) 56 | (all-vector-aux test vect 0 (vector-length vect))) 57 | 58 | (define (string? str) 59 | (and 60 | (vector? str) 61 | (all-vector char? str))) 62 | 63 | (define (list? x) 64 | (or (null? x) 65 | (and (pair? x) 66 | (list? (cdr x))))) 67 | 68 | 69 | ;;Iterate: 70 | 71 | (define ($ p n x) 72 | (or (zero? n) 73 | ($ p n (p x)))) 74 | 75 | 76 | ;; List Processing 77 | 78 | (define (reverse-aux lst acc) 79 | (if (null? lst) 80 | acc 81 | (reverse-aux (cdr lst) (cons (car lst) acc)))) 82 | 83 | (define (reverse lst) 84 | (reverse-aux lst '())) 85 | 86 | (define (append l m) 87 | (if (null? l) m 88 | (cons (car l) 89 | (append (cdr l) m)))) 90 | 91 | (define (map-aux proc lst acc) 92 | (if (null? lst) 93 | acc 94 | (map-aux proc (cdr lst) (cons (proc (car lst)) acc)))) 95 | 96 | (define (map proc lst) 97 | (reverse-aux (map-aux proc lst '()) '())) 98 | 99 | (define (map-2-aux proc lst1 lst2 acc) 100 | (if (or (null? lst1) (null? lst2)) 101 | acc 102 | (map-2-aux proc (cdr lst1) (cdr lst2) (cons (proc (car lst1) (car lst2)) acc)))) 103 | 104 | (define (map-2 proc lst1 lst2) 105 | (reverse-aux (map-2-aux proc lst1 lst2 '()) '())) 106 | 107 | (define (zip x y) 108 | (map-2 cons x y)) 109 | 110 | (define (length-aux lst acc) 111 | (if (null? lst) 112 | acc 113 | (length-aux (cdr lst) (+ acc 1)))) 114 | 115 | (define (length lst) 116 | (length-aux lst 0)) 117 | 118 | (define (fold-right f z xs) 119 | (if (null? xs) 120 | z 121 | (f (car xs) (fold-right f z (cdr xs))))) 122 | 123 | (define (fold f z xs) 124 | (if (null? xs) 125 | z 126 | (fold f (f z (car xs)) (cdr xs)))) 127 | 128 | (define (for-each proc lst) 129 | (if (null? lst) 130 | #t 131 | (begin 132 | (proc (car lst)) 133 | (for-each proc (cdr lst))))) 134 | 135 | (define (all test lst) 136 | (or (null? lst) 137 | (and (test (car lst)) 138 | (all test (cdr lst))))) 139 | 140 | (define (for-both p x) 141 | (p (car x)) 142 | (p (cdr x))) 143 | 144 | (define (member v lst) 145 | (if (null? lst) 146 | #f 147 | (if (equal? v (car lst)) 148 | lst 149 | (member v (cdr lst))))) 150 | 151 | 152 | ;; Apply! 153 | 154 | (define (apply fnc lst) 155 | (assert (procedure? fnc)) 156 | (assert (list? lst)) 157 | (asm "PUSH AFPh") (asm "PUSH AFPl") 158 | (asm "PUSH CCPh") (asm "PUSH CCPl") 159 | (asm "LDI GP1, hi8(pm(sp_apply_ret))") 160 | (asm "PUSH GP1") 161 | (asm "LDI GP1, lo8(pm(sp_apply_ret))") 162 | (asm "PUSH GP1") 163 | lst 164 | (asm "MOVW CCPl, CRSl") 165 | (asm "sp_loop_begin:") 166 | (asm "MOVW CRSl, CCPl") 167 | (asm "CALL inline_car") 168 | (asm "PUSH CRSl") (asm "PUSH CRSh") 169 | (asm "MOVW CRSl, CCPl") 170 | (asm "CALL inline_cdr") 171 | (if (not (null? (asm "MOVW CCPl, CRSl"))) 172 | (asm "RJMP sp_loop_begin")) 173 | (length lst) 174 | (asm "MOV PCR, CRSl") 175 | fnc 176 | (asm "IN AFPl, SPl") (asm "IN AFPh, SPh") 177 | (asm "MOVW GP5, AFPl") 178 | (asm "JMP proc_call") 179 | (asm "sp_apply_ret:") 180 | (asm "POP CCPl") (asm "POP CCPh") 181 | (asm "POP AFPl") (asm "POP AFPh")) 182 | 183 | 184 | ;; Vector Processing 185 | 186 | (define (fevstep proc vect i n) 187 | (if (< i n) 188 | (begin 189 | (proc (vector-ref vect i)) 190 | (fevstep proc vect (+ i 1) n)))) 191 | 192 | (define (for-each-vector proc vect) 193 | (fevstep proc vect 0 (vector-length vect))) 194 | 195 | (define (fevrstep proc vect i) 196 | (proc (vector-ref vect i)) 197 | (if (> i 0) 198 | (fevrstep proc vect (- i 1)))) 199 | 200 | (define (for-each-vector-reverse proc vect) 201 | (fevrstep proc vect (vector-last vect))) 202 | 203 | (define (vlstep vect i n acc) 204 | (if (< i n) 205 | (vlstep vect (+ i 1) n (cons (vector-ref vect i) acc)) 206 | acc)) 207 | 208 | (define (make-writer vect index) 209 | (lambda (value) 210 | (vector-set! vect index value) 211 | (set! index (+ index 1)))) 212 | 213 | (define (vector-concat left right) 214 | (let ((destination (make-vector (+ (vector-length left) (vector-length right))))) 215 | (free! 216 | (let ((writer (make-writer destination 0))) 217 | (for-each-vector writer left) 218 | (for-each-vector writer right) 219 | destination)))) 220 | 221 | ;; for backwards-compatibility, this is the old version 222 | (define (vector-copy src dest src-start src-finish dest-start) 223 | (if (> src-start src-finish) 224 | dest 225 | (begin 226 | (vector-set! dest dest-start (vector-ref src src-start)) 227 | (vector-copy src dest (+ src-start 1) src-finish (+ dest-start 1))))) 228 | 229 | ;; this is the SRFI-43-compliant version 230 | (define (vector-copy! dest dest-start src src-start src-finish) 231 | (if (> src-start src-finish) 232 | dest 233 | (begin 234 | (vector-set! dest dest-start (vector-ref src src-start)) 235 | (vector-copy src dest (+ src-start 1) src-finish (+ dest-start 1))))) 236 | 237 | (define (sub-vector vect start finish) 238 | (vector-copy vect (make-vector (+ (- finish start) 1)) start finish 0)) 239 | 240 | (define (vector-first-step vect test start) 241 | (if (or (>= start (vector-length vect)) (test (vector-ref vect start))) 242 | start 243 | (vector-first-step vect test (+ start 1)))) 244 | 245 | (define (vector-first vect test) 246 | (vector-first-step vect test 0)) 247 | 248 | (define (vector->list vect) 249 | (reverse (vlstep vect 0 (vector-length vect) '()))) 250 | 251 | (define (list->vector lst) 252 | (let ((vect (make-vector (length lst)))) 253 | (free! 254 | (for-each (make-writer vect) lst)))) 255 | -------------------------------------------------------------------------------- /src/treeshaker.c: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Treeshaker 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #include "common.h" 8 | #include "lexer.h" 9 | #include "parser.h" 10 | #include "scoper.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | char *currentDefinition = NULL; 18 | 19 | int numUsedGlobals = 0, numPurgedGlobals = 0; 20 | 21 | extern Environment *globalEnv; 22 | 23 | void treeshaker_shakeExpr(AST_expr *expr) 24 | { 25 | 26 | int i; 27 | 28 | switch (expr->type) 29 | { 30 | // The simple ones (recursion only): 31 | case Constant: break; 32 | case ProcCall: 33 | // fall through 34 | case TailCall: 35 | treeshaker_shakeExpr(expr->proc); 36 | // fall through 37 | case Branch: 38 | // fall through 39 | case When: 40 | // fall through 41 | case Sequence: 42 | // fall through 43 | case PrimCall: 44 | // fall through 45 | case OtherFundemental: 46 | // fall through 47 | case And: 48 | // fall through 49 | case Or: 50 | // fall through 51 | case Lambda: 52 | for (i = 0; i < expr->numBody; i++) 53 | { 54 | treeshaker_shakeExpr(expr->body[i]); 55 | } 56 | break; 57 | case Assignment: treeshaker_shakeExpr(expr->body[0]); break; 58 | 59 | case Definition: // Nothing to do; 60 | if (expr->numBody == 1) 61 | { 62 | if (globalEnv->realAddress[expr->varRefIndex] >= 0) 63 | { 64 | currentDefinition = expr->variable; 65 | expr->type = Assignment; 66 | treeshaker_shakeExpr(expr->body[0]); 67 | expr->type = Definition; 68 | currentDefinition = NULL; 69 | } 70 | } 71 | 72 | break; 73 | 74 | case Variable: 75 | if (expr->varRefType == Global) 76 | if (!currentDefinition || (strcmp(expr->variable, currentDefinition) != 0)) 77 | globalEnv->references[expr->varRefIndex] = globalEnv->references[expr->varRefIndex] + 1; 78 | 79 | break; 80 | } 81 | } 82 | 83 | void treeshaker_purge(void) 84 | { 85 | numUsedGlobals = 0; 86 | numPurgedGlobals = 0; 87 | 88 | int i; 89 | for (i = 0; i < globalEnv->numBinds; i++) 90 | { 91 | //fprintf(stderr, "<%s> %i\n", globalEnv->binding[i], globalEnv->references[i]); 92 | if (globalEnv->references[i] > 0) 93 | { 94 | globalEnv->realAddress[i] = numUsedGlobals; 95 | numUsedGlobals++; 96 | globalEnv->references[i] = 0; 97 | } 98 | else 99 | { 100 | numPurgedGlobals++; 101 | globalEnv->realAddress[i] = -1; 102 | //fprintf(stderr, ">> Aggressive: Global <%s> will be purged.\n", globalEnv->binding[i]); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/treeshaker.h: -------------------------------------------------------------------------------- 1 | /* ======================= Microscheme ======================= 2 | * Treeshaker 3 | * (C) 2014-2021 Ryan Suchocki, et al. 4 | * http://github.com/ryansuchocki/microscheme 5 | */ 6 | 7 | #ifndef _SHAKER_H_GUARD 8 | #define _SHAKER_H_GUARD 9 | 10 | extern void treeshaker_shakeExpr(AST_expr *expr); 11 | 12 | extern void treeshaker_purge(void); 13 | 14 | extern int numUsedGlobals; 15 | extern int numPurgedGlobals; 16 | 17 | #endif 18 | --------------------------------------------------------------------------------