Pius Arhanbhunde
Pius Arhanbhunde

Reputation: 193

Unifying file scheme/path across Windows and Unix based OS in Rascal

What is the best way to handle directory across windows and Unix based file systems in Rascal MPL, such that user of the Rascal project can read and generate files in those OS appropriately?

Upvotes: 1

Views: 61

Answers (1)

Jurgen Vinju
Jurgen Vinju

Reputation: 6696

It depends on the situation.

  • If you just need to make sure the code works on both Windows and Unix, then it's best not to type in root paths yourself. So use home:/// or tmp:/// or project://<name>, or use IO::findResources.
    • with these root paths use + to get to the children: path + "myFile.rsc" will take care of the proper escaping, encoding and add the path separator /
    • you can use myPath.ls to get a list of entries in a folder. Also in util::FileSystem there are more operations that work on any location to get an overview of a filesystem.
    • all the API in the IO module is independent of the OS, remove, lastModidied, etc. etc.
  • if you are migrating analysis results from one machine to the other, then the URIs may be different. For example, you have |file:///C:Program%20Files/| as a literal in your analysis results or in your intermediate M3 models. In this case, all your downstream analysis will work correctly, except that jumping to the code will not work properly (since the code on your Mac doesn't have that folder.
    • You can go back to the original analysis machine, and try to use the above advice, such that machine dependent file URIs dissappear. Unfortunately for some libraries like clair this does not work. They always produce file:/// URIs.
    • You can write a transformation of the information where you replace the original locations in the model with your new information. The function IO::relativize is elemental here. It will give you the postfix unique path name by removing the given prefix, if it fits. So relativize(|file:///C:Program%20Files|, |file:///C:Program%20Files/Hello.txt|) produces relative:///Hello.txt. Then you can add the relative path to the new path: newPath + relative.path. Such a transformation is lineair in the size of the model and could take a few seconds! Typically you would visit { case loc l => ...} in a few lines of code that write all locations where necessary.
  • If you want to write files from one OS into another, then you can simply construct the location, ship the data to the other side, and execute your generator there. So on my Mac I would create location: |file:///C:Program%20Files/Hello.txt|, send it to the Windows machine and there when used by writeFile it would have the desired effect.

In short:

  • Rascal URI (location) values are just values. They don't mean anything special until they are given to an IO function. They serve as identities and they can be shipped over the network or communicated on a drive without issue.
  • The module IO functions are generic, they work on all the OSs in the same way.
  • Paths and URI schemes have to exist on the OS where the IO function is executed, otherwise, you simply get IO exceptions.

Upvotes: 2

Related Questions