Closed technomancy closed 1 year ago
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: https://github.com/technomancy/microscheme/commit/3a8838560c40755ef2e3d150f95d996b9008bf4c
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.
Ahh... I see now that it's happening inside the parser; I did not expect that.
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
No, in my case having some means of portability is more important than making it work seamlessly with include; I can include both files and simply switch between the two at runtime. Thanks.
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?