-
Notifications
You must be signed in to change notification settings - Fork 3
INCLUDE documentation
Include is a Rebol script processor. It is implemented as a function and works as a Rebol script loader, preprocessor and evaluator. It is not an "alternative module system", in fact, it is orthogonal to any such system, meaning that it can work together with such a system.
- A comfortable Rebol script evaluator:
- Can preprocess and evaluate any script (the script does not have to contain prebol directives).
- Processes prebol directives facilitating SDK debugging.
- During preprocessing errors are enhanced to inform in which file the error occurred to make debugging more comfortable.
- Uses include-ctx/path which resembles paths of many operating systems to search for scripts.
- include-ctx/path can contain URLs, not just local directories.
- include/check prevents scripts from being re-included (included more than once).
- Processes ordinary scripts with Rebol header.
- Processes prefaced Rebol scripts, i.e., Rebol scripts with preface preceding Rebol header and embedded Rebol scripts (see http://www.rebol.com/docs/core23/rebolcore-5.html#section-1.2).
- An improved script loader:
- include/only just loads and preprocesses a script yielding a Rebol block.
- include/link loads a script, preprocesses it and saves the result to the specified file.
- An improved preprocessor:
- Processes all prebol directives and is compatible with SDK.
- The #include-check directive is available as a "don't re-include" variant of the #include directive.
- It is possible to include small parts of scripts like binary data, images or strings.
- Context encapsulation is available using the
make object!
or themake module!
method. - Users can define new directives.
Licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
The preprocessing phase is used to build the script, i.e., to include the necessary parts. Moreover, it enables the user to evaluate any Rebol expression(s).
Include a script (a file or URL) here. The script is preprocessed by include.
The same as above, except that the script is not included if present in the include-ctx/log.
Do the given code block during preprocessing including the result here without preprocessing it further.
Include the given text-file as a string.
Include the given binary-file as a binary.
Include the files from the file-list looking for them in the given dir directory. The files are included as a block containing name and the binary contents of all files.
Leave out the COMMENT directive and its argument from the code. The comment is not left out if the keep-comments global variable is defined when the directive is processed.
Conditionally include the given then-block if the cond-block evaluates true. The then-block is preprocessed when included.
Conditionally include one of the two blocks depending on the result of evaluation of the given cond-block. The block being included is preprocessed.
The include word refers to the include function.
The include-ctx word refers to the object containing important include variables and helper functions.
The implementation patches the script? function when needed.
The path word refers to a block containing the paths where the include function shall look for the files.
If the script file to include is specified with a non-empty path the script file is looked up only at its path. As opposed to that when the script file is specified without any path using only a file name include will use the include-ctx/path to look for the file.
The path can be modified/set by users. See also the include-ctx/push and include-ctx/pop helper functions.
The directories (or URLs) that are first in the include-path are searched first. Consequently they are having priority during the file search.
The log variable refers to a block containing the files (with complete paths) include function processed. It is used by the /check
refinement and by the #include-check
directive to check whether a specific file was already included. The default Rebol comparison (which is case-insensitive) is used and the paths are converted to lowercase.
The user can save the log to a file to create a log file. The user can influence what will be considered as "already included", typically by clearing the contents of the log block when starting to link a new file. The files are appended to the log block as they are found by include, which means that the file found last will be the last one in the log.
The stack used by the push and pop helper functions (see below). There is no need to use the variable directly.
Handling a subblock or paren.
The definitions of #if and #either conditional directives.
The definitions of the standard directives (all except the block directive, conditional directives and special includes).
The definitions of #include-binary, #include-string and #include-files directives.
The directives variable refers to the block containing the definitions of directives that are currently used by include. There is usually no need to handle this variable directly since include-ctx/get-directives, include-ctx/set-directives and include-ctx/update-directives take care of it.
The standard-header variable refers to the script header prototype object. Defined for compatibility between Rebol 2 and Rebol 3.
The file variable refers to the file processed by INCLUDE.
The function used by include and by directives to preprocess a script.
The function used by include-script and by directives to preprocess a block or a paren. Generated by the set-directives function.
Refers to a function returning the directives block used by include. The directives block is the block containing the definitions of all include directives.
Refers to a function setting the directives block used by include.
Refers to a function updating the directives (not modifying the block, though) using the given directives-to-update block. If a directive contained in the directives-to-update block is already present in the directives block it is updated. Otherwise it is appended as a new directive.
The usage of the set-directives function to update/add new include directives is not particularly comfortable. This function should be used as a more comfortable helper.
Sometimes it is desirable to be able to temporarily redefine the include-ctx/path while being able to restore its previous value after some time. The push function takes a new-path argument storing the current path contents to the stack and using the given new-path instead.
Restores the previous path value from the stack. It is the counterpart of the push function. If the stack is empty, an error is triggered.
Do next expression, using the "Rebol 3 convention", compatible with Rebol 2 and Rebol 3.
Load the next value, compatible with Rebol 2 and Rebol 3.
Read a binary value from a source, compatible with Rebol 2 and Rebol 3.
Make the error according to the given specifications, compatible with Rebol 2 and Rebol 3, allows setting the NEAR and WHERE attributes even in Rebol 2.
Disarm the error, compatible with Rebol 2 and Rebol 3.
"enhance" (if needed) and redo the given error.
Create and trigger a new include-type error.
Splits the given path.
Find the given file using the given search path.
Find a file (using INCLUDE-CTX/PATH if desired).
A new INCLUDE error type is defined, with the following ids:
This error represents an, otherwise "normal" error that occurred during code preprocessing. The error is "enhanced" to "know" the file in which it occurred.
A file or a URL was expected in the PATH.
The POP function found the STACK to be empty.
The file to be included was not found.
The directive expected an argument.
The UPDATE-DIRECTIVES function obtained an invalid directive specification in the DIRECTIVES-TO-UPDATE block.
A call equivalent to prebol processing %somefile.r
and storing the result of the preprocessing to %outfile.r
would look like:
include/link %somefile.r %outfile.r
To change the include-ctx/path:
append include-ctx/path url-or-directory
The include call corresponding to the #include-check
directive is include/check
, which preprocesses and runs the script only if it hasn't done so before:
include/check %somefile.r
The distinction between preprocessing directives and "normal" include usage is best described on simple examples:
The first example uses include, but not the preprocessing directives:
Rebol [
File: %script-builder.r
]
; create a new "standard" script from the script base
verbose: false
; use a clean LOG
clear include-ctx/log
include/link %script-base.r %standard-script.r
; now create a verbose version
verbose: true
clear include-ctx/log
include/link %script-base.r %verbose-script.r
To create the two versions of the script containing everything they need to run it is sufficient to do:
include %script-builder.r
, which takes care of creating both script versions.
The %script-base.r
file can look e.g. as follows:
Rebol [
File: %script-base.r
]
#either [verbose] [debug: :print] [debug: none]
#include-check %part1.r
#include-check %part2.r
...
It is possible to encapsulate contexts as follows:
Rebol [
Title: "my script"
]
make object! [#include %your-script.r]
make module! [[module spec goes here] [#include %his-script.r]]
New directives are defined using set-directives function or, more comfortably, using the update-directives function, which allows selective updating of include directives. The directives are written in the parse dialect. Even the standard directives are defined this way; it is possible to take their definition as an example.
The directives block is bound to the include-block function context by the set-directives function. Furthermore, the user can bind his directives block to the include-ctx context if his directives use some of the include-ctx functions or variables.
The locals of the include-block function are:
In the definitions of the standard directives it is being used to hold the current position in the block (or paren) being included. This variable can be and frequently is redefined.
In the definitions of the standard directives it is being used to hold the next position (the position following the currently processed directive part) in the block (or paren) being included.
This variable can be and frequently is redefined.
In the definitions of the standard directives it is being used to hold the first argument value of the currently processed directive.
This variable can be and frequently is redefined.
In the definitions of the standard directives it is being used to hold the second argument value of the currently processed directive.
This variable can be and frequently is redefined.
In the definitions of the standard directives it is being used to hold the third argument value of the currently processed directive.
This variable can be and frequently is redefined.
The #print directive is meant as the debug-print directive. It uses (potentially) the debug flag to "decide" whether to turn the directive into a print call, or simply leave it out from the code together with its argument.
Usage:
#print argument
If the debug flag (global) is defined (set) when the #print directive is being processed the directive is turned into a print call; otherwise it is left out from the code.
Rebol [
Title: "Debug-print"
File: %debug-print.r
Author: "Ladislav Mecir"
Date: 21-Oct-2011/15:31:41+2:00
Purpose: {Defines the #print directive}
Notes: {
uses the debug flag (global)
if the debug flag is set, #print becomes print
otherwise, #print and its argument are left out
}
]
include-ctx/update-directives [
#print set value1 skip (
if value? 'debug [
append linked 'print
append/only linked get/any 'value1
]
)
]
To be compatible with do include changes the working directory to that of the script it is processing. Note that relative paths are relative to the actual working directory, not to the directory that was actual when such paths were put into the include-ctx/path block.
For example if we define:
include-ctx/path: reduce [%. clean-path %.]
at the first sight it seems that the two elements in the above include-ctx/path are equivalent, but that is not true. The first one is a relative path always referring to the current working directory while the second one refers to the directory that was current when the include-ctx/path was defined.
This directive evaluates an expression and includes its result 2 into the script:
#do [1 + 1]
while this one evaluates the expression as well including nothing:
#do [1 + 1 []]
When a script is running you may need to find out whether it has been preprocessed or not. Here is how:
print either (#do [false]) ["this code wasn't preprocessed"]["this code was preprocessed"]
Sometimes you want a part of the script to remain untouched by the preprocessor. This is a way how:
#do [[
; this part will not be preprocessed
prin "part1: "
print either (#do [false]) ["not preprocessed"] ["preprocessed"]
]]
; this part will be preprocessed
prin "part2: "
print either (#do [false]) ["not preprocessed"] ["preprocessed"]
Using the above trick we can do it as follows:
#do [[[
print mold #include
]]]
The %include.r
script may serve as an example of a script containing the preprocessor directives. Still you may want to write such a script so that its behaviour is the same whether it has been run by do or include.
Combining the tricks from the previous sections:
do if (#do [false]) [func [a b] [do first b]] #do [[
; here we can put any code with preprocessor directives
; without worrying whether the user ran the script using DO or INCLUDE:
print mold #include
; etc.
]]
Another alternative - this time it is a block that remains unprocessed no matter whether the script is processed by do or include:
do either (#do [false])[func [a b] [b/1/1]] [func [a] [:a]] #do [[[
; here I can put any code with or without preprocessor directives
print mold #include
]]]
To create a Windows Explorer association so that you can right-click on a .r
file to run it using include:
- Download the
%include.r
script. - Create a script file including any script
- This is an example file (use your own directory paths):
Rebol [
Title: "Incl.r3"
File: %incl.r3
Author: "Ladislav Mecir"
Date: 30-Sep-2011/10:23:03+2:00
Purpose: {Includes the first argument file, works with Rebol 3}
]
; define the INCLUDE function
do %include.r
;---- Rebol 3 GUI
include %/d/ladislav/saphirion/trunk/r3-gui/loader/loader.r3
; include the argument script
include to-rebol-file system/script/args
- Add a new association for
.r
files. (Actually, you can add more associations. For example, I have one calledr2
to evaluate the script using include and Rebol 2 interpreter and one calledr3
to evaluate the script using include and the Rebol 3 interpreter.)
Run the Windows Explorer and click on Tools/Options
in menu. Next click on the File Types
tab and find the .r
file type associations. Click on the Advanced
button and add a new action. Call the new action r3
and the application associated with the new action may be e.g.:
"D:\Rebol\r3.exe" d:\rebol\incl.r3 "%1"
(Adjust your directory appropriately). Next you can decide whether to make the r3
action default. If you make it default you can just double-click (or left-click if you set your Explorer for one click as I did) on a .r
file to include it. Otherwise you can right-click the file in Windows Explorer and pick the r3
action from the quick menu.
- Run the
regedit.exe
program - Find the
HKEY_CLASSES_ROOT\.r
key - Examine its
(Default)
value, should be something liker_auto_file
- Find (or create) the
HKEY_CLASSES_ROOT\r_auto_file
key - Find (or create) the
HKEY_CLASSES_ROOT\r_auto_file\shell
subkey - Under the
shell
key find (or create) a newopen
subkey and a newr3
subkey - Under the
open
key add a newcommand
subkey - Change the
(Default)
value of thecommand
key to something like"D:\Rebol\rebol.exe" d:\rebol\incl.r "%1"
(do not forget to use your directory paths). - Under the
r3
key add a newcommand
subkey - Change the
(Default)
value of thecommand
key to something like"D:\Rebol\r3.exe" d:\rebol\incl.r3 "%1"
(do not forget to use your directory paths).
.r
files left-clicking a .r
file will run it in the rebol.exe
interpreter while right-clicking a .r
file in the Windows Explorer you will see new open
and r3
options, being able to choose which interpreter you want to start.
In the same way you can define the open
association for .r3
files.
Include is available from http://www.rebol.org/view-script.r?script=ladislav-include.r.
8-Apr-2013/13:00:27+2:00
- INCLUDE/LINK now using MOLD/FLAT
- INCLUDE/only update
- to help Cyphre use it for encapping purposes
- returns the Rebol header spec part in the result block if available
- license updated to Apache 2.0
- header processing reimplemented to really work
- header handling changed
- it is not a requirement to have a script header now in a manner compatible with Rebol 3 DO
- the 'FILE variable moved from the INCLUDE-BLOCK context to INCLUDE-CTX
- scripts can read the variable now,
- "knowing" what is being processed (before, only directives "knew" the variable)
- INCLUDE-CTX/LOAD-NEXT function defined
- for compatibility with Rebol 2 and Rebol 3
- SCRIPT? function patched
- INCLUDE function:
- result corrected in a couple of special cases
- help strings improved
- source punctuation improved
- documentation updated
- addition of the STANDARD-HEADER variable to INCLUDE-CTX
- script header processing added
- doc update
- the complete file made available from the rebol.org site
- adding the READ-BINARY function to INCLUDE-CTX
- updating the #include-binary and #include-files directives to work in Rebol 3
- circumventing the APPEND bug in Rebol 2
- /only refinement defined for the UPDATE-DIRECTIVES function
- SPECIAL-INCLUDES defined
- the "in-file" bug in standard directives corrected
- "pointer" file posted to rebol.org
- include-ctx/standard-directives subdivided (block-directive defined)
- the block directive corrected (the correct value1 variable used)
- a new invalid-directive include error defined
- the update-directives function updated to trigger the invalid-directive error
- include type errors documented
- changes documented
- directive identification adjusted
- block-directive adjusted to be identifiable
- #if, #either, #do, #include-files directives adjusted
- include-ctx/conditional-directives defined (improving the support for localization or other user-defined sets of directives)
- include-ctx/standard-directives defined (all standard directives except for the conditional ones)
- comments in the code updated
- no incompatibilities with the previous version expected
- update-directives function adjusted to not modify the directives block, replacing it instead (safer)
- update-directives function defined
- the debug-print example changed to use update-directives
- comments added to the code
- the #include-binary and #include-string directives adjusted
- handling the situations when the find-file function doesn't find the given file
- doc changes
- RebGUI create-distribution problem solved
- the COMMENT directive made standard
- the include-ctx context defined
-
include variables (see above) moved to the include-ctx context
- (watch out for the obsolete use of include-path, include-log, include-push and include-pop)
- all helper functions moved to the include-ctx context (see above)
- , which makes it easier for the user to use any of the helper functions in his own directives
- the include-parser function does not exist anymore
- the set-directives function now generates the include-block function
- the localize-block removed from the standard code
- (localization code now more complex, but more separate from the "standard code")
- error handling changed
- include error type defined
- the make-error function can define the near and where error attributes even in Rebol 2
- the #print directive definition reflects the include changes
- documentation updated
- more comments in the %include.r file
- %include.r code cleaned up
This article describes how include was ported to Rebol 3.