Jared Forsyth
11/09/2024, 1:22 PMMisha A
11/09/2024, 2:56 PMThe structured editor that I'm buildingfor which language(s)?
Jared Forsyth
11/09/2024, 3:16 PMMisha A
11/09/2024, 3:38 PMstructured
for you?
Syntax as in "commas, parens, semicolons" (collections and atoms) is just a part of the story.
Other part is semantic meaning of that syntax.
For example the difference in meaning of tokens in (+ 1 2 3)
vs (if 1 2 3)
,
or meaning of vector([]
) elements in (defn foo [a b] ...)
vs (let [a b] ...)
.
This is why both "lisp has almost no syntax" and "lisp code is AST" - BS.
> Ultimately it's an editor for developing new languages
"editor for new clojure/lisp macros" would be nice test/milestone/challenge for it.
I tried to approach same/similar problem recently as "DSL for custom macros support for Clojure IDE", because condo
configs are nightmare: https://clojurians.slack.com/archives/C06AH8PGS/p1713614069031559
(https://clojurians-log.clojureverse.org/instaparse/2024-04-20)Misha A
11/09/2024, 3:45 PMJared Forsyth
11/09/2024, 4:16 PM(+ 1 2 3)
and (if 1 2 3)
the same is the right spot for editor manipulation.
And then a language's parser converts this "concrete syntax tree" into an ASTJared Forsyth
11/09/2024, 4:17 PMMisha A
11/09/2024, 6:40 PMJared Forsyth
11/09/2024, 7:37 PMname
of the function `flatMap`" that's not a line/col pair that will break at the slightest touch, unlocks a lot of nice things)
• jupyter/observable/etc. style super-REPL/literate programming environment for pure functional languages
• unison-style "terms are referenced by the hash of their contents, stored and synced in a database"
• a Development Environment for programming languages themselves, making it easy to iterate and play with various aspects of a programming language (compilation targets, execution semantics, type inference algorithms) in relative isolation, as well as enabling the bootstrapping of self-hosted languagesJared Forsyth
11/09/2024, 7:40 PMJared Forsyth
11/09/2024, 7:42 PMMisha A
11/09/2024, 7:54 PM(+ 1 2 3)
and (if 1 2 3)
the same is the right spot for editor manipulation` because all you get is some-hash[0][1][0][6]
(nested array address) or something w/o knowledge what +
or defn
means.
re unison: YES. designing new lang w/o even giving it a try to be "content-addressable" – ...
it solves/simplifies/amplifies so much later on in the toolchain: deps, version control, diffs/reviews, (structural)editing.
(in my like 4th spare time I try to retrofit content-addressability onto at least a subset of clojure, which too started elsewhere: from custom macros, to kondo-config for it, to "screw it - I'm writing myself a clojure IDE with blackjack", to "might as well make bake in addressability and distribution for source control, because git is both overkill and underwhelming (like any text-files-diffing SCM)")Jared Forsyth
11/09/2024, 7:56 PM(+ a b c)
is actually a map of node-id to node, 0=list(1 2 3 4), 1=id(+, ref=hash of the + function), 2=id(a, ref=hash of the a term)
etcJared Forsyth
11/09/2024, 7:57 PM+
in (defn + [a b] ...)
is addressable as some-toplevel-id : the-loc-of-that-id-node
Jared Forsyth
11/09/2024, 7:59 PMJared Forsyth
11/09/2024, 8:00 PMMisha A
11/09/2024, 8:01 PMhash[1st][0th][7th]
or am I not seeing something?
also how is "hash of a func" different from "hash of a term"?
so you have some "rule" that "1st item in a () list - function call"? that's a semantical knowledge I mentionedJared Forsyth
11/09/2024, 8:01 PMJared Forsyth
11/09/2024, 8:02 PMMisha A
11/09/2024, 8:04 PMdefn
vs let
:
(defn foo [x y] ...)
R N N N
(let [x y] ...)
R N R
and that is semantic knowledge, not just "collections and atoms"Jared Forsyth
11/09/2024, 8:06 PMJared Forsyth
11/09/2024, 8:07 PMMisha A
11/09/2024, 8:07 PMC
+ scope (which R
are known, and which are error))
(defn foo [x y] ...)
R N N N
(quote (defn foo [x y] ...)
R C C C C
Jared Forsyth
11/09/2024, 8:08 PMJared Forsyth
11/09/2024, 8:08 PMJared Forsyth
11/09/2024, 8:09 PMMisha A
11/09/2024, 8:09 PMJared Forsyth
11/09/2024, 8:10 PMJared Forsyth
11/09/2024, 8:10 PMJared Forsyth
11/09/2024, 8:12 PM(defn a [b] c)
probably looks like id=x45r, root: 37, nodes: 37=list(11 3 7 1), 11=id(defn, ref=builtin), 3=id(a, ref=null), 7=array(20), ...
. So "the name of that defn" is (x45r, 3)
Misha A
11/09/2024, 8:12 PMJared Forsyth
11/09/2024, 8:13 PMJared Forsyth
11/09/2024, 8:13 PMMisha A
11/09/2024, 8:13 PMdefn
or (defn ...)
?Jared Forsyth
11/09/2024, 8:14 PMa
is what I meant to be referncingJared Forsyth
11/09/2024, 8:14 PMJared Forsyth
11/09/2024, 8:16 PM(deftype (option a) (some a) (none))
Jared Forsyth
11/09/2024, 8:16 PMsome
have a durable reference to the id that defines the name of it, so renames are trivialMisha A
11/09/2024, 8:29 PMforward + backward example:
0
1 2
3
(let [a x b a] [a b])
4
5
6 7
8 8 ;; a and b have parallel scope at this point
parallel example:
0
1 2
4 3 4 3 5
6 6
(binding [a 1 b 2] [a b])
;;The new bindings are made in parallel (unlike let);
also notice, that in let
, b
ejects/exports its cope from vector to body [a b]
, but body does not export scope outside let (propagation stops).
So spread direction is based on the meaning of first symbol, and the fact that 1st symbol meaning is important - is a higher level semantic tooMisha A
11/09/2024, 8:32 PMexport
is created global definition: in (defn foo [a b] body)
defn
exports foo
to the global scope, but not a
b
or body
.
which is solely semantics of defn
Jared Forsyth
11/09/2024, 8:32 PMJared Forsyth
11/09/2024, 8:32 PMMisha A
11/09/2024, 8:32 PMMisha A
11/09/2024, 8:33 PMJared Forsyth
11/09/2024, 8:36 PMMisha A
11/09/2024, 8:38 PMJared Forsyth
11/09/2024, 8:47 PMMisha A
11/09/2024, 8:49 PMdefn
is not the same as defn
which is meant to be looked up and resolved as e.g. clojure.core/defn
so either you need to prompt user on every word "is it a ref or is it static/literal?", or forbid literals, or rely on semantics of something in the text before the word, again, in clojure: '
or quote
, which is a semantic not just "colls and atoms"Misha A
11/09/2024, 8:53 PMJared Forsyth
11/09/2024, 9:02 PMJared Forsyth
11/09/2024, 9:03 PMJared Forsyth
11/09/2024, 9:04 PMMisha A
11/09/2024, 9:04 PMJared Forsyth
11/09/2024, 9:04 PMJared Forsyth
11/09/2024, 9:05 PMJared Forsyth
11/09/2024, 9:07 PMMisha A
11/09/2024, 9:07 PMJared Forsyth
11/09/2024, 9:07 PMJared Forsyth
11/09/2024, 9:07 PMMisha A
11/09/2024, 9:07 PMJared Forsyth
11/09/2024, 9:08 PMJared Forsyth
11/09/2024, 9:08 PMJared Forsyth
11/09/2024, 9:08 PMJared Forsyth
11/09/2024, 9:10 PMMisha A
11/09/2024, 9:13 PMdefn
is a macro, it receives foo
and a b
all 3 foo a b
exist in global scope (= can be resolved, and are resolved before being passed into macro)
now defn
throws away resolution and assigns new roles of global
to `foo`and local
to a
and b
?Jared Forsyth
11/09/2024, 9:14 PMMisha A
11/09/2024, 9:14 PMfoo a b
are not in the globals, resolution resolves to 'unknown' and passes that to defn
?Jared Forsyth
11/09/2024, 9:14 PMJared Forsyth
11/09/2024, 9:14 PMMisha A
11/09/2024, 9:15 PMbuilt in
you mean semantics (scope propagation rules, locals/globals export) baked in into "parser"
?Misha A
11/09/2024, 9:17 PMdefn
being macro in clojure (bottoms out to def
), and all those prismatic.schema/defschema
etc. basically any macro exporting new global?Jared Forsyth
11/09/2024, 9:17 PMJared Forsyth
11/09/2024, 9:17 PMJared Forsyth
11/09/2024, 9:18 PMMisha A
11/09/2024, 9:18 PMdefn
knows what is new global, and what is args (new locals). and you resolve them before defn
gets themJared Forsyth
11/09/2024, 9:19 PMMisha A
11/09/2024, 9:19 PMJared Forsyth
11/09/2024, 9:19 PMMisha A
11/09/2024, 9:20 PMfoo
is ok to be unresolved at this particular place: second token inside (defn foo ...)
listJared Forsyth
11/09/2024, 9:21 PMMisha A
11/09/2024, 9:21 PMfoo
in the (defn foo)?Jared Forsyth
11/09/2024, 9:22 PMMisha A
11/09/2024, 9:22 PMMisha A
11/09/2024, 9:23 PMJared Forsyth
11/09/2024, 9:27 PMJared Forsyth
11/09/2024, 9:28 PMJared Forsyth
11/09/2024, 9:29 PMJared Forsyth
11/09/2024, 9:30 PMMisha A
11/09/2024, 9:33 PMIn fact it would be a parser error to use a resolved id as the "name of what I'm exporting"can't redefine things this way.
(def foo 1)
(def foo 2) ;; exports already resolved(able) global foo
Jared Forsyth
11/09/2024, 9:34 PMMisha A
11/09/2024, 9:35 PM(def elsewhere/foo 1) ;)
Jared Forsyth
11/09/2024, 9:36 PMMisha A
11/09/2024, 9:37 PMJared Forsyth
11/09/2024, 9:37 PMMisha A
11/09/2024, 9:38 PMJared Forsyth
11/09/2024, 9:38 PMJared Forsyth
11/09/2024, 9:39 PMJared Forsyth
11/09/2024, 9:39 PMJared Forsyth
11/09/2024, 9:39 PMMisha A
11/09/2024, 9:39 PMJared Forsyth
11/09/2024, 9:40 PMJared Forsyth
11/09/2024, 9:40 PMMisha A
11/09/2024, 9:40 PMJared Forsyth
11/09/2024, 9:40 PMMisha A
11/09/2024, 9:41 PMJared Forsyth
11/09/2024, 10:10 PMJared Forsyth
11/09/2024, 10:12 PMJared Forsyth
11/09/2024, 10:13 PMAlexander Bandukwala
11/12/2024, 6:04 PMJared Forsyth
11/12/2024, 6:05 PMMisha A
11/12/2024, 9:05 PMJared Forsyth
11/13/2024, 3:35 PMAlexander Bandukwala
11/13/2024, 5:02 PMJared Forsyth
11/13/2024, 5:14 PMJared Forsyth
11/13/2024, 5:14 PMMisha A
11/16/2024, 10:30 AM/* ... */
//
;
#_
(comment ...)
• markers/indentation as denotation of nestedness (python): >
>>
\t