ryansuchocki / microscheme

A Scheme subset for Atmel microcontrollers.

Home Page:http://ryansuchocki.github.io/microscheme/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Conditional compile-time settings

technomancy opened this issue · comments

I've got a project that would benefit from being able to pass a flag at compile-time in to embed it in the code.

I would imagine it would be difficult to do this in a way that's portable to other schemes, but maybe using get-environment-variable along the lines of SRFI-98 would make sense, with the caveat that the value is fixed at compile-time? Or would it be better to use a completely different name?

I think implementing (the 1-argument form of) get-environment-variable is a sensible way of doing this. The main caveat is that (get-environment-variable "FOO") will be equivalent to a string literal in terms of memory usage (specifically, 2n bytes on the heap which can only be recovered using free!). In usage, it will be prudent to keep the (get-environment-variable) out of any loops and keep the values as short as possible.

Another option would be to implement something like the current @if-model primitive, but this is probably more work.

I took a very rough shot at implementing this here: technomancy@3a88385

In my patch I attempt to replace the get-environment-variable expression with a string literal. However, when I tested it, it doesn't work:

(include (get-environment-variable "LAYOUT"))
LAYOUT=layout.scm microscheme -m LEO menelaus.scm
Microscheme 0.9.3, (C) Ryan Suchocki
>> ERROR 18: First operand to INCLUDE should be STRING
Makefile:25: recipe for target 'menelaus.s' failed
make: *** [menelaus.s] Error 1

Any ideas what might be going on there?

This is because, in microscheme, include is not really a function. It's a fundemental form. Specifically, this means that the contents of the included file are parsed and embedded into the abstract syntax tree before any code generation occurs. (If this were not the case then we would require multiple cycles of parsing and code generating before all includes are resolved...)

Since get-environment-variable is implemented as a primitive function, the transformation (into a string) occurs too late for it to work as the argument to include. To have it work in this scenario we would need to make get-environment-variable itself a fundamental form, and then do something more complex in the lexer and/or parser.

If using the environment variable with include is important then the cleanest way to achieve it is probably to use some special atomic (i.e. not involving parentheses) character sequence like %VARNAME. Such a character sequence could be transformed very early on (i.e. in the lexer) into a string literal token and then it would behave exactly the same as a string literal in all fundemental forms, including (include %LAYOUT). It would be a shame not to have compatibility with other schemes but there is probably no perfect solution here because we are getting into territory where the difference between compilation and interpretation start to matter a lot.