Compiler/Simple file inclusion pre processor: Difference between revisions
Content added Content deleted
(→{{header|Wren}}: Revised following latest clarification.) |
|||
Line 601: | Line 601: | ||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
⚫ | |||
I'm not really sure how this task relates to languages such as Wren which (despite limited compilation) are basically interpreters so, despite what it says in the task description, I'll confine this entry to describing the situation. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
All the modules listed on the language's main page need to be imported in this way. |
All the modules listed on the language's main page need to be imported in this way. |
||
Line 614: | Line 612: | ||
It will therefore be seen that Wren neither has nor needs a pre-processor; it doesn't support macros or other text substitution devices and imports are always in source code rather than binary form. |
It will therefore be seen that Wren neither has nor needs a pre-processor; it doesn't support macros or other text substitution devices and imports are always in source code rather than binary form. |
||
Nevertheless, it is possible to write a limited pre-processor in Wren (the VM itself is written in C): |
|||
<lang ecmascript>import "io" for File |
|||
var source = File.read("source.wren") |
|||
var ix |
|||
var start = 0 |
|||
while ((ix = source.indexOf("import", start)) && ix >= 0) { |
|||
var ix2 = source.indexOf("\n", ix + 6) |
|||
if (ix2 == -1) ix2 = source.count |
|||
start = ix + 1 |
|||
var imp = source[ix...ix2] |
|||
var tokens = imp.split(" ").where { |s| s != "" }.toList |
|||
var filePath = tokens[1][1...-1] |
|||
if (filePath.startsWith("./")) { |
|||
filePath = filePath[2..-1] |
|||
} else if (filePath.startsWith("/")) { |
|||
filePath = filePath[1..-1] |
|||
} else { |
|||
continue // leave resolution of other modules to compiler |
|||
} |
|||
var text = File.read(filePath + ".wren") |
|||
source = source[0...ix] + "\n%(text)\n" + source[ix2..-1] |
|||
} |
|||
File.create("source2.wren") { |file| file.writeBytes(source) }</lang> |
|||
<br> |
|||
The above code is limited in the sense that '''all''' top-level variables of the imported module (not just the specifically imported ones) are now visible in the outer scope. Consequently, the code will no longer compile if there are any name clashes. |
|||
The obvious solution of placing the imported code in a block and then 'lifting' the specifically imported variables into the outer scope does not work because of Wren's rather strange scoping rules. If you did this, then the imported module's top level variables would no longer be top-level relative to the code as a whole and hence would no longer be visible to classes defined within the module itself! For example, if you try to run the following script, you get the error shown: |
|||
<lang ecmascript>var B |
|||
{ // block starts here |
|||
var A = 2 |
|||
class C { |
|||
static method1() { |
|||
System.print(A) // Error at 'A': Variable is used but not defined. |
|||
} |
|||
} |
|||
B = C |
|||
} // end of block |
|||
B.method()</lang> |
|||
Other problems include dealing with '''import''' statements which have been commented out (not catered for in the above pre-processor) and resolving import file paths which is not actually set in stone but depends on how Wren is being embedded. The above pre-processor code only deals with paths which are relative to the current directory. |