How to produce a .js file from a haskell source file with haste? - haste

So I noticed, while answering this question, that the one who asked the question appears to be a javascript developer. And as the code I wrote in haskell is easy enough, I thought I give haste a try and try to compile it to javascript.
So, I downloaded the Windows binary package of haste (why does the .msi require a reboot?!!?), added it to my path, issued haste-cabal update and haste-cabal install split and after a bit of reading the output of hastec --help, I issued:
PS E:\h\stackoverflow> hastec -o hexagon.js --pretty-print hexagon.hs
as my best guess on how to get the output I am looking for.
Opposite to my expectation, haste output was this:
hastec.exe: user error (shell expression failed in readModule: Data.Binary.Get.runGet at position 8: not enough bytes)
So, my question: What do I have to do to get a java script source file?

Is it possible that you have an old version of Haste lying around, or have intermediate files (.jsmod, for instance) from a different version of the compiler in your source directory? This sounds like the (quite unhelpful) error message Haste produces when it runs into a corrupted intermediate file.
Check that the version of the binary you're calling is what you expect (hastec --version). Then, try getting rid of all intermediate files in the directory as well as any files in %USERPROFILE%\AppData\Roaming\haste, reinstalling split, and recompiling with the -fforce-recomp flag. You should also add a main function, so that Haste has an entry point to your program from which to start linking. If all you want to do is to make some Haskell function available to external JavaScript, you can use the export foreign function interface:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Haste.Foreign
import Hexagon
main = export "picture" Hexagon.picture
You will probably also want to compile your program with the --onexec flag, to make sure that main runs and exports picture immediately when loaded, and not on page load which is the default:
> hastec -o hexagon.js --pretty-print --onexec hexagon.hs
After doing this, any code included after hexagon.js will be able to call e.g. Haste.picture(5); in order to produce a picture of size 5.
(Re: MSI installer requiring a reboot, this is required since it adds the Haste binaries to your %PATH%, which does not take effect immediately. I assume that a re-login would be enough to make it take effect, however.)

Related

Running a Matlab p-file coded for Windows on a MacOS

I have several Windows sourced p-files internally coded with the '\' file separator that I want to run on Matlab under macOS.
I get errors caused by the '\' because macOS uses '/'.
eg The pfile tries to call a file named "model\xyz' which causes a warning:
"Name is nonexistent or not a directory: model\ "
1) Is there code that I might insert somewhere to recognise the 'model\' call from the pcode file and change it to 'model/' before it is used by MATLAB addpath?
2) Is there a generic fix I could apply to the addpath code?
3) Or better still is there a way to modify the Windows p-file without access to its source code so that it will run under macOS?
There are several things you can do (none of which are particularly easy; listed here in increasing order of how nasty I think they are):
Contact the author of the code and ask them to fix it.
Install an older MATLAB version (R2007b <= ver < R2015b, I think) which allowed debugging (stepping into) p-files within MATLAB, then, assuming that there is some line in the original source code that does
filepath = ['model' '\' 'xyz.m'];
step until you see filepath appear in the workspace (having the wrong path in it), then simply edit the value to the correct path, and hope for the best.
(Essentially the same idea as before, but on newer MATLAB versions, VERY DIFFICULT to pull off) Obtain an external debugger, attach to the MATLAB process, run the p-file and scan the memory for the contents of filepath. When you discover it, change the value to the correct path and detach/disable the debugger.
If this code relies on some external (and open source) function to get (or use) the path, you can modify its behavior to output the string you want. This requires some knowledge about the source code.
Find/make a tool for decoding p-files and fix the resulting source code yourself.
For completeness I describe how my problem was solved:
As suggested by Dev-iL I was eventually able to locate the author and he modified his code. This is the best solution but it took some time and is not always possible.
Based on: https://au.mathworks.com/matlabcentral/answers/117110-dealing-with-and-windows-vs-unix-for-path-definition I located a module (I've forgotten its name) within the Matlab package which handles file calls and intercepted all incoming file path names containing the '\' Windows separator, and replaced them with the always acceptable '/'. This quick and dirty fix worked until solution 1. was obtained.
Thanks to all who responded so quickly to this question.

Opening .py files with micropython on TI Nspire

I uploaded Fabian Vogt's micropython port to my TI Nspire CX CAS, together with a couple of *.py.tns files to try. I can't find a way to load/launch those files.
As micropython does not include the os module, I can't use os.chdir to change the current directory and load the *.py files from the python shell. I tried from python shell: open("documents/mydirectory/myfile")
with different extensions .py or .py.tns, without success.
I don't think the Nspire has anything like the terminal commmand line either.
Thanks for your help,
There are 2 ways that you could do this, one easy way and one tedious way.
1. Map .py to micropython in your ndless.cfg
(ndless.cfg should be at /documents/ndless/ndless.cfg)
Like so:
ext.xxx=program-name
ext.xxx=program-name
ext.txt=nTxt
ext.py=micropython
ext.xxx=program-name
ext.xxx=program-name
You can edit this file either by copying it back and forth from your computer using TiLP or the official software, or you can edit it on-calc using nTxt. (This requires a bit of fiddling with making a copy of ndless.cfg so that the mappings still exist to open the copied file ndless.txt).
Ndless should come with a standard ndless.cfg containing basic bindings for nTxt and a few popular emulators. If you don't have one, get the standard one here. It will scan all directories (at least /documents/*, AFAIK) for programs. I've found that removing lines related to programs not on your Nspire will decrease load time.
2. Proper way to run a file in Python
To run a file in Python, you should do something like this:
with open("/documents/helloworld.py.tns","r") as file:
exec(file.read())
This will properly close the file after executing, which I've noticed is quite important on the Nspire, as leaving files open has given me trouble before. Of course, if you'd like, you can do exec(open("...","r").read()) and then handle closing the file yourself, but be warned: bad things can happen if you forget.
Also, you must remember to add the leading / and the .tns extension, or else strange things will happen, especially with writing to files.
That's about it! Feel free to ask more questions if needed, I'll be watching the ti-nspire tag.
(Just realized this question is quite old, but I guess it still might be helpful for others who end up on empty questions months later while trying to figure something out :P)

Perl/CPAN how to distribute script rather than module

I just published my first perl program, unifdef+ (code::unifdefplus, v0.5.3), but I'm not sure if I've done it properly. The program is broken into two parts -- a script (script/unifdef+.pl), and a module (lib/unifdefplus.pm). The script is basically a wrapper for the module. This is supposed to act as a command line utility (which is in reality what I wanted to publish).
The README file I included documents the script, not the module. CPAN seems to be taking the version from the module rather than the script as well (which is undefined at the moment).
So, my questions is: if I want this to be indexed as a script rather than a module, do I need to do anything differently? Also, I'm taking it I should write some documentation for the module as well -- in which case I'm assuming it should be a README file in the lib directory?
Again, I apologize, but this is the first time I've done this, and I want to make sure I've done it right.
Right off the bat, please read On the naming of modules from the PAUSE admins. If you still have questions, or you're still unsure, reach out to modules <at> perl.org.
The simplest way is to use a name in the App:: namespace, such as App::MyMod.
Typically, I'd keep the script and module documentation within their separate files, but near the top of the module documentation, clearly link to the script's documentation, and state that most users will want to read that for normal use.
To build the README from the script documentation:
pod2readme bin/my_script
Likewise, if you change your mind and want README to reference the module instead:
pod2readme lib/App/MyMod.pm
Assuming you're using ExtUtils::MakeMaker for your builds, you can ensure that the script is installed by adding a directive:
EXE_FILES => [
'bin/my_script'
],
With of course your script in the top-level bin directory of your distribution. Other build systems have similar directives.

How to import files relative to main file, instead of current directory? ((Chez) Scheme)

For example, in my main.scm file I have (load "util.scm"). util.scm is a file in the same folder as main.scm. Both files are located in ~/documents/myproject/.
Now when I'm in this directory, and I run $ chez-scheme main.scm everything works fine. However, if I'm in my home directory and run $chez-scheme documents/myproject/main.scm it complains, not being able to find the file util.scm. I suppose this is the case because the current directory was my relevant home directory, and as such util.scm is indeed not there, it is actually in documents/myproject/. That being said, I'm used (in other languages) to the functionality of looking these paths up relative to the file containing the instruction to import, and I'd like to have that here as well. I've tried prefixing it by ./ or defining the file as a libary and doing (import (util)) but none of it works outside of documents/myproject/. Is there any way to get this to work as I intend it to?
I assume this is Chez-Scheme-specific. If not I'd prefer an answer that is implementation-neutral.
load is kind of awkward in R5RS since the report states that system interfaces are off topic in the report, but they include load which is a half hearted solution. The report does not say if the load is relative to the current directory or the file the load form originates from so in order to be portable I guess you are required to run your script from the current directory and have your loaded file relative to both.
Since Chez Scheme implements R6RS load is not really the right form to use. R6RS removed load in favor of libraries. You should make your file a library and consult how to install it. In some systems that is just placing the files in the right path, adding library location in configuration or running install script. How one uses the library is the same in all implementations, by using import.
According to Chez documentation you can pass --libdirs to it to give it one or more paths to consider for loading libraries. You can see the paths it scans by evaluating (library-directories)
There are several different ways to accomplish what (I think) you are trying to do, but eventually they all boil down to letting Chez know where to look for things. When given relative paths, include and load use the source-directories parameter to search for the requested file. Libraries have their path automatically prepended to source-directories while they are being loaded or compiled, so if your main.scm were a library definition then it would find util.scm as you expect.
However, it sounds like main.scm isn't a library, it's a top-level program. Unfortunately, Chez doesn't have a command line option to set the source-directories like it does for library directories. That leaves you with a bit less flexibility. Any of the following will work:
Make util.scm a library and invoke Chez with the --libdirs option to let it know where to look for libraries.
Set source-directories and load main.scm from inside the REPL rather than from the command line.
Write a wrapper shell script that does the above by echoing the commands into scheme so you don't have to type it yourself. (Only suitable if you don't also need to then type into the scheme session).
Write a wrapper shell script that cds into your project directory before running scheme (and presumably cds back to the original directory when it's done).

Swift Command Line tool needs other file

So I have a script that takes an input and prints whatever. It needs access to a file written by a third party. My Xcode project structure is just two files, main.swift and ThirdParty.swift. If I just run it from Xcode main.swift happily sees ThirdParty.swift and I'm apply to instantiate an object defined within. When I run from the command line it cannot find ThirdParty.swift (which is pretty much to be expected; how would it know it's there?).
None of the command line options to pass to /usr/bin/swift seem to be appropriate for pointing to a file I'd like to use and pointing it to the current directory doesn't work either. Is this even possible or should I just give up?
The ideal end result is the ability to do something like:
./main.swift --option1 --option2 thing
But an acceptable place to end up would be:
swift -X ThirdParty.swift main.swift --option1 --option2 thing
Where X is whatever option I need to be passing in.
You can't pass two files into "immediate" mode (swift REPL mode) but you have several other options:
Combine the files together on the fly into a temporary file (with e.g. /bin/cat)
Compile the two files into a normal binary with swiftc.
I recommend option 2, though it means every time you change the code you'll need to recompile, and the binaries it creates aren't portable between OS X and Linux.