We Need A Syntax For "IMPORT Relative To System.Script.Path"

I'm moving ahead with DO of a script (or running on the command line) not changing the current working directory. It's an important and overdue change.

So if you run:

/home/me$ r3 /usr/local/scripts/something.r ./foo.txt

Then when something.r is called it will still be in /home/me, and it will resolve foo.txt to /home/me/foo.txt by default. That's good.

But if you then have:

Rebol [File: %something.r]

import %utilities.r

Then this will look for utilities.r in /home/me as well.

I think that is the correct behavior for a relative %file path. So the real issue is just that there needs to be another syntax to tell IMPORT to look relative to SYSTEM.SCRIPT.PATH.

TL;DR: I Think This Should Be TAG!

This will be very common, and unlike the library lookup it will tend to be more than one word long. I think being enclosed in angle brackets has a nice look.

Rebol [Title: "My Big Script"]

import <common.r>
import 'altxml
import 'json/1.2.1
import <subsystems/gui-manager.r>
import <subsystems/icon-manager.r>

do/args <utils/something.r> :[1 + 2 3 + 4]

Here I'm suggesting bumping just to WORD! for loading libraries from the index, since TAG! would have this new meaning.

I'm Avoiding Types That Are Valid Branches

One of the rules I made a while ago was that if a type is accepted by a branch in a control structure, that DO should have the same behavior for that datatype.

Of course we know blocks are legal branches and do the same thing:

>> if true [1 + 2]
== 3

>> do [1 + 2]
== 3

But I want the rule to extend to all the other types. So in a world where if true @json has meaning as a branch, I wouldn't want do @json to do anything different.

So that limits the choices a bit here for this feature. Because I want you to be able to DO or LOAD things from the library of named utilities, just as you can IMPORT them.

And now with this feature of DO and LOAD relative to system.script.args, I'd like that to work as well.

Refinements Are Not Going To Be Palatable

Firstly, I'd challenge you to come up with a good name for it:

import/here %foo.r

But for how common the desire is, this just doesn't look good.

Filenames Should Be Unconstrained By WORD! Rules

One might suggest reversing the suggestion I made, where you use WORD!/PATH! for the local files and keep the TAG! for the name lookups:

Rebol [Title: "My Big Script"]

import 'common.r
import <altxml>
import <json>/v.1.2
import 'subsystems/gui-manager.r
import 'subsystems/icon-manager.r

do/args 'utils/something.r :[1 + 2 3 + 4]

But this gets you involved with issues about file paths not having full coverage in the domain of WORD!s. What if you want to load something and it's relative to the script directory?

smiley: load <icons/png/smiley 32x32.png>

Using TAG! for this helps avoid problems here. Whereas the name lookup service is entirely something we invent, and so constraining it to legal words makes perfect sense.

Why Not Use ISSUE! Instead of TAG! ?

This could also let TAG! stay used how it is:

Rebol [Title: "My Big Script"]

import #common.r
import <altxml>
import <json>/v.1.2
import #subsystems/gui-manager.r
import #subsystems/icon-manager.r

do/args #utils/something.r :[1 + 2 3 + 4]

But I don't care for it, and I've suggested ISSUE! will be used in the import dialect for hashes.

Thoughts welcome. I know this is going to create some compatibility problems, but we can have a grace period where scripts will fall back on tags to look them up... so there will be time to fix things while still moving on with the new rules.

Currently import 'my-mod searches for %my-mod.reb in system/options/module-paths.
Will this stay as it is?

We'll need to find a way to get everything everyone wants to do in the syntax. What makes this hard is that with the rule that DO must act as any branch would, then DO has so many meanings for types already. :-/

It makes it tempting to get some other word in there. Of course, there's LOAD.

do load @json
do load 'json

That's fairly succinct. And it could then mean that do @json and do 'json could have different behavior more mechanically related to branches.

Earl said a long time ago that he thought DO was too overloaded. I think he wanted the basic DO to just run BLOCK!s and to have all the other mechanics pulled out to something else.

It's a bit of a loss to not have the syntax of just do <tool>...and if we went full in on the idea then it would mean we'd lose do %file.r too. :frowning:

It could be another word, like run %file.r and run <tool>. Maybe RUN could also be variadic, and take a number of args that the tool would take on the command line.

$ r3 some-script.r arg1 arg2

>> run %some-script.r arg1 arg2

This could take the pressure off DO for its argument types, allowing it to 100% match how branches act, and always be running on already-LOAD-ed data.

Then RUN + LOAD + IMPORT could share a concept of how they interpret types to locate source.

:question:

If this all aligns, then I don't yet have a strong opinion on:

import 'local-module
import @json

import @local-module
import 'json

Either would work. But there is also the bigger question of IMPORT syntax for when it has more options...that needs to be thought through.

import [
    @json
    /version 1.2.1  ; syntax for fields, to save reserved-words?
    parse-json  ; just import a thing by name?
    jget: get-json  ; be able to rename an import?
]

I thought this looked kind of crappy and asked for instance if we might be able to "sniff" blocks variadically in the import statement:

import @json [
    /version 1.2.1  ; syntax for fields, to save reserved-words?
    parse-json  ; just import a thing by name?
    jget: get-json  ; be able to rename an import?
]

And maybe even do more with sensing. I feel like noticing SET-WORD! on the left to give a name to the import is sort of a non-negotiable thing:

j: import @json

But it makes import a little harder for people to adapt import, the weirder and more "sensing" it gets. It's probably worth it.

Here's what I said about contrast with JavaScript import

Lots of unanswered questions! But, maybe this RUN idea can help untie our hands. Or maybe it's backwards...and DO should remain the version for running files, and some other function is needed for evaluating values as branch-types...

So I'm finding it very tempting to take a cue from C and use a TAG!/TEXT! distinction. Then we'd just have bonus variations:

import <some/location.r>  ; search standard libs

import "some/location.r"  ; search relative to file's directory

import %some/location.r  ; search relative to OS-notion of current directory
    ; ^-- you would rarely want to do this, but could in some dynamic
    ; situation where a caller told you where the library it wanted you to use
    ; was, relative to it...

import http://example.com/whatever.r  ; Direct URL

This might allow us to even say that you can look for "standard libraries" local on your machine vs. remote, by omitting the extension (C++ does something along these lines)

import <json>  ; don't touch the network, but get standard JSON

import @json  ; search online module index and get a remote JSON

It would at least feel familiar, if we went that route.

Fighting over the TEXT! with DO and LOAD

The main problem with using TEXT! here goes back to the overlap in meaning that DO (and IMPORT has) where you can DO text and it loads as the BLOCK!.

DO'ing strings is rare enough (and a bit too ambiguous, anyway) that I'd be happy to just bump that off to say you should produce a block and then DO that. But then you just bumped the problem over to DO LOAD where LOAD has the ambiguity of TEXT!. You'd have to say that LOAD only loads blocks from BINARY!. :frowning:

Got to remember this is design...it's okay to iterate!

2 Likes

IMPORT/HERE

or only if you like :wink:

For what it is worth C programmers would already be used to it. And RenC devs know what it means in C without getting confused.