diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-05-01 21:31:45 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-05-01 21:31:45 -0700 |
commit | 065dde19dfbe50e91e313e5b3ccc033cfbe47f74 (patch) | |
tree | 2ba6874a603e014b4be5e7e273eac2b62bae2ab5 | |
parent | 488c1ba59416a0b2ce87a36d7df3026e334d66b9 (diff) | |
download | txr-065dde19dfbe50e91e313e5b3ccc033cfbe47f74.tar.gz txr-065dde19dfbe50e91e313e5b3ccc033cfbe47f74.tar.bz2 txr-065dde19dfbe50e91e313e5b3ccc033cfbe47f74.zip |
loading: try unsuffixed files directly last.
In this patch we change the strategy for resolving unsuffixed
paths in load and @(load). In load, an unsuffixed name is
tried with a .tlo suffix, then .tl and only if those don't
resolve to a file it is tried as-is. The previous order is
as-is, .tlo, .tl. Similarly in @(load), but unsuffixed paths
are tried as .txr, then .tlo, then .tl.
The motivation for this is to avoid probing the filesystem
multiple times the optimized case that we care about: loading
.tlo files from Lisp.
* parser.c (open_txr_file): Rearrange the probing strategy.
Also recognize .txr_profile as a suffix, treating it like .tl.
This is so that we don't probe for .txr_profile.tlo and
.txr_profile.tl before finding the profile.
(load_rcfile): Take advantage of the new path-not-found
exception. We avoid wastefully checking with path-exists-p
to avoid calling open_txr_file. We just let open_txr_file
throw an exception if the file doesn't exist, and then
distinguish the non-existence case in the handler.
* txr.1: Updated @(load) and load documentation.
-rw-r--r-- | parser.c | 75 | ||||
-rw-r--r-- | txr.1 | 166 |
2 files changed, 145 insertions, 96 deletions
@@ -439,58 +439,67 @@ void open_txr_file(val spec_file, val *txr_lisp_p, val *name, val *stream) suffix = tl; else if (match_str(spec_file, lit(".tlo"), negone)) suffix = tlo; + else if (match_str(spec_file, lit(".txr_profile"), negone)) + suffix = tl; else suffix = none; errno = 0; { - val spec_file_try = spec_file; - FILE *in = w_fopen(c_str(spec_file_try), L"r"); + val spec_file_try = nil; + FILE *in = 0; - if (in != 0) { - switch (suffix) { - case tl: - *txr_lisp_p = t; - break; - case tlo: - *txr_lisp_p = chr('o'); - break; - case txr: - *txr_lisp_p = nil; - break; - default: - break; - } - } - -#ifdef ENOENT - if (in == 0 && errno != ENOENT) - goto except; - errno = 0; -#endif - - if (suffix == none && in == 0 && !*txr_lisp_p) { + if (suffix == none && !*txr_lisp_p) { spec_file_try = scat(lit("."), spec_file, lit("txr"), nao); in = w_fopen(c_str(spec_file_try), L"r"); #ifdef ENOENT if (in == 0 && errno != ENOENT) goto except; - errno = 0; #endif } - if (suffix == none) { if (in == 0) { spec_file_try = scat(lit("."), spec_file, lit("tlo"), nao); + errno = 0; in = w_fopen(c_str(spec_file_try), L"r"); *txr_lisp_p = chr('o'); +#ifdef ENOENT + if (in == 0 && errno != ENOENT) + goto except; +#endif } if (in == 0) { spec_file_try = scat(lit("."), spec_file, lit("tl"), nao); + errno = 0; in = w_fopen(c_str(spec_file_try), L"r"); *txr_lisp_p = t; +#ifdef ENOENT + if (in == 0 && errno != ENOENT) + goto except; +#endif + } + } + + if (in == 0) { + spec_file_try = spec_file; + errno = 0; + in = w_fopen(c_str(spec_file_try), L"r"); + if (in != 0) { + switch (suffix) { + case tl: + *txr_lisp_p = t; + break; + case tlo: + *txr_lisp_p = chr('o'); + break; + case txr: + *txr_lisp_p = nil; + break; + default: + break; + } } } @@ -705,10 +714,6 @@ static void load_rcfile(val name) val stream = nil; val catch_syms = cons(error_s, nil); val path_private_to_me_p = intern(lit("path-private-to-me-p"), user_package); - val path_exists_p = intern(lit("path-exists-p"), user_package); - - if (!funcall1(path_exists_p, name)) - return; uw_catch_begin (catch_syms, sy, va); @@ -730,9 +735,11 @@ static void load_rcfile(val name) uw_catch(sy, va) { (void) va; - format(std_output, lit("** type ~s exception while loading ~a\n"), - sy, name, nao); - format(std_output, lit("** details: ~a\n"), car(va), nao); + if (stream || sy != path_not_found_s) { + format(std_output, lit("** type ~s exception while loading ~a\n"), + sy, name, nao); + format(std_output, lit("** details: ~a\n"), car(va), nao); + } } uw_unwind { @@ -8500,27 +8500,39 @@ Where is a Lisp expression that evaluates to a string giving the path of the file to load. -If the +Firstly, the path given by +.meta expr +is converted to an effective path, as follows. + +If the value of the .code *load-path* -has a current value which is not +variable has a current value which is not .code nil and the path is pure relative according to the .code pure-rel-path-p -function, then the path is interpreted relative +function, then the effective path is interpreted taken relative to the directory portion of the path which is stored in .codn *load-path* . If .code *load-path* -is nil, or the load path is not pure relative, then it the path is -taken as-is. +is nil, or the load path is not pure relative, then the +path is taken as-is as the effective path. -If the file named by the path cannot be opened, then the +Next, an attempt is made to open the file for processing, in +almost exactly the same manner as by the \*(TL function +.codn load . +The difference is that if the effective path is unsuffixed, +then the .code .txr -suffix is added and another -attempt is made. Thus load expressions need not refer to the suffix. -In the future, additional suffixes may be searched (compiled versions -of a file). +suffix is added to it, and that resulting path is tried first, +and if it succeeds, then the file is treated as \*(TX Pattern +Language syntax. +If that fails, then the suffix +.code .tlo +is tried, and so forth, as described for the +.code load +function. Both the .code load @@ -8529,44 +8541,57 @@ and directives bind the .code *load-path* variable to the path of the loaded file just before parsing syntax from it, -and remove the binding when their processing of the file is complete. -Processing \*(TL code means that each of its forms is read, and evaluated. -Processing \*(TX code means parsing the entire file in its entirety, -and then executing its directives against the current input. - The +.code *package* +variable is also given a new dynamic binding, whose value is the +same as the existing binding. These bindings are removed when the +load operation completes, restoring the prior values of these +variables. + +If the file opened for processing is \*(TL source, or +a compiled \*(TL file, then it is processed in the manner +described for the +.code load +function. + +Different requirements apply to the processing of the file under the .code load and .code include -directives differ as follows. -The action of +directives. + +The +.code include +directive performs the processing of the file at parse time. If the +file being processed is \*(TX Pattern Language, then it is parsed, +and then its syntax replaces the +.code include +directive, as if it had originally appeared in its place. +If a \*(TL source or a compiled \*(TL file is processed by +.code include +then the +.code include +directive is removed from the syntax. + +The .code load -is not performed immediately but at evaluation time. Evaluation time +directive performs the processing of the file at evaluation time. +Evaluation time occurs after a \*(TX program is read from beginning to end and parsed. That is to say, when a \*(TX query is parsed, any embedded .code "@(load ...)" forms in it are parsed and constitute part of its syntax tree. -They are executed when that query is executed and its execution +They are executed when that query is executed, whenever its execution reaches those .code load -directives. - -By contrast, the action of -.code include -is performed immediately, right after the -.code "@(include ...)" -directive syntax is parsed. That is to say, as the \*(TX parser encounters -this syntax it processes it immediately. The included material is read -and processed. If it is \*(TX syntax, then it is parsed and incorporated -into the syntax tree in place of the -.code include -directive. The parser then -continues processing the original file after the -.code include -directive. If \*(TL code is processed by the -.code include -directive, then its forms are read and evaluated. An empty directive -is substituted into the syntax tree in this case. +directives. When the +.code load +directive processes \*(TX Pattern Language syntax, it parses +the file in its entirety and then executes that file's directives +against the current input position. Repeated executions of the +same +.code load +directive result in repeated processing of the file. Note: the .code include @@ -58399,43 +58424,60 @@ directory. Once the effective path name is determined, .code load -first tries to open that exact path name. -If this succeeds, then the file will be treated as containing \*(TL, -unless -.meta target -ends with the +determines whether the name is suffixed. The name is suffixed if it +ends in any of these four suffixes: +.codn .tlo , +.codn .tl , .code .txr -suffix, in which case the file will be treated as containing -\*(TX pattern language syntax, or ends with the suffix -.code .tlo -in which case it will be treated as a compiled file. +or +.codn .txr_profile . -If loading the original effective path name fails, and that name is unsuffixed, -then the +Depending on whether the effective path name is suffixed, +.code load +tries to make one or more attempts to open several variations of that name. +If any attempt fails due to an error other than non-existence, +such as a permission error, then no further attempts are made; the +error exception propagates to +.codn load 's +caller. + +If the effective path name is suffixed, then +.code load +tries to open a file by that exact path name. If that attempt +fails, no other names are tried. + +If the effective path name is unsuffixed, then first the suffix .code .tlo -suffix is added and a second attempt is made. If that succeeds, the file -is treated as a compiled \*(TL file. -Otherwise, the suffix +is appended to the name, and an attempt is made to open a file +with this path. If that file is not found, then the suffix .code .tl -suffix is added to the original unsuffixed name, and one more attempt is made. -If that succeeds, the file will be treated as \*(TL. +is similarly tried. If that file is not found, then the unsuffixed +name is tried. -If a file is successfully resolved and opened for \*(TL processing, -then \*(TL forms are read from it in succession. Each form is evaluated as if -by the +If an unsuffixed file is opened, its contents are treated as interpreted Lisp. +Files ending in +.code .txr_profile +are also treated as interpreted Lisp. Files ending in +.code .tlo +are treated as compiled Lisp, and those ending in +.code .txr +are treated as the \*(TX Pattern Language. + +If the file is treated as \*(TL, then Lisp forms are read from it in +succession. Each form is evaluated as if by the .code eval function, before the next form is read. If a syntax error is encountered, an exception of type .code eval-error is thrown. -If a file is successfully resolved and opened for processing as a -compiled \*(TL object file, then the compiled images of top-level forms -are read from it, converted into compiled objects, and executed. +If a file is treated as a compiled \*(TL object file, then the compiled images +of top-level forms are read from it, converted into compiled objects, and +executed. -If a file is successfully resolved and opened for \*(TX processing, -then its contents are parsed in their entirety as a \*(TX -query. If the parse is successful, the query is executed. +If the file treated as \*(TX Pattern Language code, +then its contents are parsed in their entirety. +If the parse is successful, the query is executed. Previous \*(TX pattern variable and function bindings are in effect. If the query binds new variables and functions, these emerge from the |