Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add language server package #3655

Draft
wants to merge 23 commits into
base: development
Choose a base branch
from
Draft

Conversation

d-torrance
Copy link
Member

This is a (very very very) early draft of a LanguageServer package that implements Microsoft's Language Server Protocol (LSP), which is used by multiple editors (Emacs, VSCode, etc.)

@mahrud
Copy link
Member

mahrud commented Feb 15, 2025

Is there a TODO list for this? Is the idea that LSP should fully replace the M2-mode on Emacs and extensions on Vim and VSCode? If so it would be good to have a list of M2-mode features that need to be reimplemented.

@d-torrance
Copy link
Member Author

d-torrance commented Feb 15, 2025

A TODO list would be good. For the time being, I was just focusing on getting the basic lifecycle messages working and hadn't put much thought into what actual features to implement. So current TODO list:

  • Get life cycle messages working
  • Write a TODO list :)

I don't think LSP would replace M2-mode in Emacs, just supplement it. That seems to be the case for the other major modes for languages that already have LSP support, like python-mode.

I'm also thinking of breaking the JSON-RPC stuff, which is essentially fully functional, into its own package (or maybe just add to the existing JSON package). It's not unique to LSP, and potentially might be useful for some other stuff. It's apparently widely used in cryptocurrency applications, for example.

Proof of concept now that "new X from (Y,Z)" and "new X from (Y,Z,W)"
work and we don't have to worry about checking the number of elements
or their classes at top level.
Implements basic JSON-RPC server.  Goal is to be used by
LanguageServer package.
It was added to the POSIX standard in 2001 and should be available on
all modern systems.

Since we no longer need to roll our own host_address, which used
inet_addr, we can drop the check for arpa/inet.h.
The "PF" is for "protocol family" (AF is "address family").  According
to the GNU libc manual:

"The corresponding namespace designator symbol PF_UNSPEC exists for
completeness, but there is no reason to use it in a program."
It was a thin wrapper around getaddrinfo that used a global variable
to store the error message when an error was raised.  This likely
wasn't thread safe.

Instead, we determine the error message a bit later, when it's time
to actually print it, without any global variables.  This requires a
little bit of logic to distinguish between getaddrinfo errors and
non-getaddrinfo errors.  In particular, we shift the error codes of
the getaddrinfo errors and then shift back later when we need them.
In particular:

* Use memset to initialize the hints struct instead of static (for
  thread safety)
* Actually use a hints struct in opensocket
* Loop through all the elements of the linked list returned by
  getaddrinfo until we find one that works rather than just crossing
  our fingers and going with the first one
* Use the info in the struct returned by getaddrinfo in our call to
  socket rather than hardcoding everything
* With new for loop logic, we only need a single call to freeaddrinfo.

Code heavily inspired by Beej's Guide to Network Programming:
https://beej.us/guide/bgnet
The value of status will only be accurate if the process has changed
state, i.e., if waitpid returned a positive value.  So in particular,
we won't be able to trust that fix_status will return -2 in this case
as given in the documentation.  So we return -2 manually in this case.
So many ternary conditional operators...

Also put #ifdef's around the non-POSIX WCOREDUMP as recommended in the
waitpid manpage.
Also remove some "is Error" cases -- user can't pass an Error!
For the "method already installed" error message to look okay (i.e.,
not display "MutableHashTable{...}"), we turn nullaryMethods into a
Type, which kind of makes sense anyway since it's the object we
install these methods in.
Previously, something like openOutAppend "$localhost:12345" or
openOutAppend "!cat" would cause us to write to files with these names
rather than the expected behavior.

The "Append" really doesn't mean anything -- behavior is identical to
openOut in these cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants