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

[WIP] IDE Support #1235

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a445208
Add :std/swank, some swank instructions and functions in the readme, …
drewc Jun 2, 2024
a7483b3
Add tools/gxswank with proper lib path
Jun 2, 2024
63f46f8
Merge branch 'master' into ide
drewc Jun 12, 2024
0223be0
Merge branch 'master' into ide
drewc Jun 21, 2024
21f1c46
WIP: Add `instance` syntax and doc, Parsec Monad to come
Jul 2, 2024
949a3f6
Make gxhttp pass the correct typecheck when timeout
Jul 2, 2024
2bb53ff
Change title to play with vuepress better
Jul 2, 2024
e6d82ac
Add instance to build spec
Jul 2, 2024
fa5f150
max-token-length: for gxhttpd
Jul 22, 2024
c86a49b
Change swank package path in README
Jul 30, 2024
c7df0ac
Merge branch 'master' into ide
drewc Aug 4, 2024
6b502c8
Merge branch 'master' into ide
vyzo Aug 5, 2024
d1f5a41
IDE: IDEServer interface (#1261)
vyzo Aug 6, 2024
97c11ba
WIP: All the monads needed for Parsec
drewc Aug 17, 2024
e9c49cf
WIP: Update toc in monad readme
drewc Aug 17, 2024
1ca4e8a
WIP: Monad tests should work with lib
drewc Aug 17, 2024
2a4f1b8
Merge branch 'master' into ide
drewc Aug 17, 2024
c604a66
WIP: Remove uneeded build
drewc Aug 17, 2024
0f3a317
WIP: Monad tests pass FFS!
drewc Aug 22, 2024
a198b5d
WIP: Does rebind fix tests?
drewc Aug 22, 2024
72a2e1f
Rebind in the right place, no :- where type is anything
drewc Aug 23, 2024
667855b
WIP: Major start on Parsec!
drewc Aug 31, 2024
f6758b5
fix test verbosity for monad/parsec
drewc Aug 31, 2024
0449a12
Fix monad-test imports
drewc Aug 31, 2024
ba40c39
gxtest: Add --quiet flag
drewc Aug 31, 2024
fd188f1
Add --quiet to ci workflow
drewc Aug 31, 2024
36a2d91
Fix the try combinator/lookahead at EOF
drewc Sep 1, 2024
7a32e37
Merge branch 'master' into ide
drewc Oct 16, 2024
de86a88
Merge branch 'master' into ide
drewc Dec 21, 2024
9d84e1e
Merge branch 'master' into ide
drewc Jan 13, 2025
997fb08
Fix gxhttpd bug: No content length when chunking
drewc Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/reference/std/getopt.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This is the old name of the [`:std/cli/getopt`](cli/getopt.md) module,
that provides facilities for command line argument parsing.

Up to Gerbil v0.18, `:std/getopt` was the only name for this module.
As of Gerbil v0.19, both names are supported.
Up to and including Gerbil v0.19, both names are supported.
However, we recommend you use the new name `:std/cli/getopt` from now on,
as we may remove the old name at some point in the future.

Expand Down
3 changes: 0 additions & 3 deletions doc/reference/std/instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
When defining many methods on a class, possibly with an interface wrapper, a short form is nice to reduce bloat.

::: tip To use the bindings from this module:

```scheme
(import :std/instance)
```

:::


## Introduction

Gerbil has a strong type system which is close a "Meta-language"(`ML`)! That is to say: a functional programming language with a polymorphic Hindley–Milner type system.
Expand Down
2 changes: 1 addition & 1 deletion src/gerbil/builtin.ssxi.ss
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ package: gerbil
(input-port-characters-buffered (port::t) integer::t effect: (io))
(input-port-column (port::t) integer::t effect: (io))
(input-port-line (port::t) integer::t effect: (io))
(input-port-readtable (port::t) integer::t effect: (io))
(input-port-readtable (port::t) readtable::t effect: (io))
(input-port-readtable-set! (port::t readtable::t) void::t effect: (mut io))
(input-port-timeout-set! [((port::t t::t) void::t effect: (mut io))
((port::t t::t procedure::t) void::t effect: (mut io))])
Expand Down
3 changes: 3 additions & 0 deletions src/gerbil/main.ss
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ package: gerbil
("clean" "gxpkg" "clean")
("env" "gxpkg" "env")
("pkg" "gxpkg")
("swank" "gxswank")
("test" "gxtest")
("tags" "gxtags")
("prof" "gxprof")
Expand All @@ -81,6 +82,7 @@ package: gerbil
("clean" "gxpkg" "help" "clean")
("env" "gxpkg" "help" "env")
("pkg" "gxpkg" "help")
("swank" "gxswank" "-h")
("test" "gxtest" "-h")
("tags" "gxtags" "-h")
("prof" "gxprof" "-h")
Expand All @@ -107,6 +109,7 @@ package: gerbil
(displayln " clean clean build artifactacts for a package (gxpkg clean)")
(displayln " env eval a shell command in the local package environment (gxpkg env)")
(displayln " pkg invoke the gerbil package manager (gxpkg)")
(displayln " swank run a swank server (gxswank)")
(displayln " test run tests (gxtest)")
(displayln " tags create emacs tags (gxtags)")
(displayln " prof profile a dynamic executable module (gxprof)")
Expand Down
22 changes: 22 additions & 0 deletions src/std/build-spec.ss
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,28 @@
"srfi/160/c64"
"srfi/160/c128"
"srfi/212"
"ide/model"
"ide/interface"
"ide/swank/api"
"ide/swank/message"
"ide/swank/context"
"ide/swank/autodoc"
"ide/swank/repl"
"ide/swank/presentation"
"ide/swank/top"
"ide/swank/eval"
"ide/swank/completions"
"ide/swank/handlers"
"ide/swank/server"
"ide/swank"
;; :std/monad
"monad/interface"
"monad/syntax"
"monad/identity"
"monad/list"
"monad/state"
"monad/error"
"monad"
;; :std/mime
"mime/struct"
(gxc: "mime/types" (extra-inputs: ("mime/mime.types")))
Expand Down
49 changes: 49 additions & 0 deletions src/std/ide/interface.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
;;; -*- Gerbil -*-
;;; © vyzo
;;; IDE interface
;;(import ./model)
(export #t)
(import ./model)

(interface IDEServer
;; updates the workspace tracked files
;; added, modified, and removed are lists of file paths.
(update-workspace (added : :list) (modified : :list) (removed : :list))

;; resolve a symbol in source to an entity
(resolve (src : Source)) => Entity

;; finds references of a specific entity within a scope
;; - e is the entity for which references should be searched
;; - scope can be:
;; - #f, in which case the entire workspace is searched
;; - a file path for searching a specific file/module
;; - a list of file paths for searching specific file/modules
;; returns a list of References
(find-refs (e : Entity) (scope :~ reference-scope? := #f)) => :list

;; finds documentation for an entity
;; returns a list of Location with relevant documentation
(find-docs (e : Entity)) => :list

;; complete the last symbol in a partial s-expr in some source span
;; returns a list of Completions
(complete (src : Source)) => :list

;; evals an sexpr in some source span
(eval (src : Source)) => Result

;; expands an sexpr in some source span
(expand (src : Source) (fully? : :boolean := #f)) => Result

;; visits a file/module
;; Returns a parsed representation (SExpr) of the file/module's code
(visit-file (path : :string)) => Result

;; updates the in-memory reprsentation of a file/module
(edit-file (replace-at : SourceFileSpan) (data : :string) (span : Span) ))

(def (reference-scope? o)
(or (not o)
(string? o)
(and (list? o) (andmap string? o))))
124 changes: 124 additions & 0 deletions src/std/ide/model.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
;;; -*- Gerbil -*-
;;; © vyzo
;;; IDE model types
(import :std/actor-v18/message)
(export #t)

;; base class for serializable objects; actor io
(defclass (Serializable message) ())

;; source locations and anchors
(defclass (Source Serializable) ())
(defclass (SourceString Source) ((value : :string)))
(defclass (File Serializable) ((path : :string)))
(defclass (Pos Serializable) ((line : :fixnum) (col : :fixnum)))
(defclass (Span Serializable) ((start : Pos) (end : Pos)))

(defclass (SourceFilePos Source File Pos) ())
(defclass (SourceFileSpan Source File Span) ())
(defclass (SourceFileString SourceString File) ())
(defclass (ModuleRef Serializable) ((module : :symbol)))
(defclass (SourceModuleString SourceString ModuleRef) ())
(defclass (SourceFileModuleString SourceModuleString File) ())

;; uniquely identifiable entities
(defclass (Entity Serializable)
((id : :symbol) ; the entity identifier
(name : :symbol) ; the human "name" of the entity
(ctx : :t))) ; the context of the identifier

;; base class for entity types
(defclass (Type Entity) ())

;; identifiers
(defclass (Identifier Entity)
((type :? Type)))

;; identifier types
(defclass (MetaObject Type) ())
(defclass (Class MetaObject) ())
(defclass (Interface MetaObject) ())

(defclass (Object Type) ())
(defclass (StandardObject Object) ())
(defclass (ClassInstance StandardObject) ())
(defclass (InterfaceInstance StandardObject) ())
(defclass (SystemObject Object) ())
(defclass (Procedure SystemObject) ())

(defclass (MetaSyntacticObject Type) ())
(defclass (Macro MetaSyntacticObject) ())
(defclass (Module MetaSyntacticObject) ())

;; completions
(defclass (Completion Serializable)
((symbol : :symbol) ; the completion symbol
(entity : Entity))) ; the completion entity

;; objects with a location
(defclass (Location Serializable) ((loc : SourceFileSpan)))

;; entity source references
(defclass (Reference Location)
((e : Entity))) ; the entity referred

;; evaluation and expansion results
(defclass (Result Serializable) ())

;; S-Expressions
(defclass (SExpr Result)
((hd : :symbol)
(e : :list)))

;; literal values
(defclass (Literal Result)
((value : :string)))

;; errors
(defclass (Error Result)
((msg : :string)))

;; register message classes for actor io
(defsyntax (declare-serializable stx)
(syntax-case stx ()
((_ id ...)
(with-syntax (((id::t ...)
(stx-map (lambda (id) (stx-identifier id id "::t")) #'(id ...))))
#'(begin
(register-message-type! id::t)
...)))))

(declare-serializable
Serializable
Source
SourceString
File
Pos
Span
SourceFilePos
SourceFileSpan
SourceFileString
ModuleRef
SourceModuleString
SourceFileModuleString
Entity
Type
Identifier
MetaObject
Class
Interface
StandardObject
ClassInstance
InterfaceInstance
SystemObject
Procedure
MetaSyntacticObject
Macro
Module
Completion
Location
Reference
Result
Literal
SExpr
Error)
23 changes: 23 additions & 0 deletions src/std/ide/swank.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
(import
./swank/api
./swank/message
./swank/context
./swank/presentation
./swank/eval
./swank/top
./swank/completions
./swank/autodoc
./swank/handlers
./swank/server)
(export
(import:
./swank/api
./swank/message
./swank/context
./swank/presentation
./swank/eval
./swank/top
./swank/completions
./swank/autodoc
./swank/handlers
./swank/server))
104 changes: 104 additions & 0 deletions src/std/ide/swank/README.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#+TITLE: Swank, a SLIME backend for an IDE

* SLIME and Swank: Graphical REPL

SLIME, the Superior Lisp Interaction Mode for Emacs, is an Emacs mode
for developing Lisp applications.
-- https://en.wikipedia.org/wiki/SLIME

SLIME uses a backend called Swank that is loaded into Lisp to turn
Emacs into a featured REPL along with an IDE for lisp use.

* Minimal Emacs setup

There are some developers that (**gasp**) don't use Emacs as their
primary go to application. Having said that even without using the
editor portion the REPL itself is useful and continues to grow into a
wonderful interface to Gerbil.

If you already use emacs it may be as simple as adding the following
to your init file.

#+begin_src emacs-lisp
(use-package slime
:hook ((gerbil-mode . slime-mode)))

(defun gerbil-slime-init-function (file encoding)
(format "(begin (import (prefix-in :std/ide/swank swank#))
(let ((port (+ 10000 (random-integer 55535))))
(swank#create-server port: port)
(with-output-to-file %S (cut write port))))\n\n"
file))

(cl-defun gerbil-slime-start
(&key (program "/opt/gerbil/current/bin/gerbil") program-args
directory
(coding-system slime-net-coding-system)
(init 'gerbil-slime-init-function)
(name 'gerbil)
(buffer "*inferior-gerbil*")
init-function
env)
"Start a Gerbil process and connect to it.
This function is intended for programmatic use if `gerbil-slime' is not
flexible enough.

PROGRAM and PROGRAM-ARGS are the filename and argument strings
for the subprocess.
INIT is a function that should return a string to load and start
Swank. The function will be called with the PORT-FILENAME and ENCODING as
arguments. INIT defaults to `gerbil-slime-init-command'.
CODING-SYSTEM a symbol for the coding system. The default is
slime-net-coding-system
ENV environment variables for the subprocess (see `process-environment').
INIT-FUNCTION function to call right after the connection is established.
BUFFER the name of the buffer to use for the subprocess.
NAME a symbol to describe the Lisp implementation
DIRECTORY change to this directory before starting the process.
"
(let ((args (list :program program :program-args program-args :buffer buffer
:coding-system coding-system :init init :name name
:init-function init-function :env env)))
(slime-check-coding-system coding-system)
(when (slime-bytecode-stale-p)
(slime-urge-bytecode-recompile))
(let ((proc (slime-maybe-start-lisp program program-args env
directory buffer)))
(slime-inferior-connect proc args)
(pop-to-buffer (process-buffer proc)))))

(defun gerbil-slime (&optional command coding-system)
"Start an inferior^_superior Lisp and connect to its Swank server."
(interactive)
(slime-setup)
(gerbil-slime-start))



#+end_src

Or you could [[https://slime.common-lisp.dev/doc/html/Getting-started.html#Getting-started][download it]] and put it in your =load-path=.

* Running the Swank Server in Gerbil

#+begin_src sh
gerbil swank --help
gxswank: The Gerbil HTTP Daemon

Usage: gxwank [option ...]

Options:
-g --global-env use the user global env even in local package context
-a --address <host> The IP or hostname to listen on [default: localhost]
-p --port <port> The port number on which the Swank server listens for connections [default: 4005]
-d --dont-close <dont-close> Close the acceptor on client disconnect if anything but true [default: true]
-h --help display help

#+end_src







Loading
Loading