Skip to content

Instantly share code, notes, and snippets.

@sogaiu
Last active December 20, 2025 14:21
Show Gist options
  • Select an option

  • Save sogaiu/36d04c3f33dbc56461bcd16fbfe57b73 to your computer and use it in GitHub Desktop.

Select an option

Save sogaiu/36d04c3f33dbc56461bcd16fbfe57b73 to your computer and use it in GitHub Desktop.
* code to help with "compiling" / "linking" multiple files into a
self-contained single script
* develop with files split, but "compile" to single script
* rationale
* single file can be copied and used more easily as a script or
library (e.g. easier to "vendor" into projects). though on
windows, the script idea may require an accessory `.bat` or
other launcher file.
* symlinking to single file in repository means that development
is eased because one is working with the current version without
having to "install"
* random
* consider when newer versions of jell should be "deployed"
* how about placing info in the attributes table for nodes for
reference later? e.g. during studying, record notes in attribute
tables. then during later traversals, make use of the previously
recorded info?
* while traversing code, possible to track whether one is within a
quoted or quasiquoted form and then record this either in the
attribute table or elsewhere. this might help in identifying
names that should not be renamed (e.g. peg specials or other
similar situations)?
* combine with idea of having "directives" marking areas (spans?)
or nodes to indicate that jell should behave differently?
* adopt approach of noting limitations and potential features but
waiting until need is dire, painful, etc.?
* document some details of what kind of .janet files can be "brought
together"
* limits and questions
* make small projects for testing
* removes `comment` forms
* removes docstrings
* changes all syntactically top-level definitions to private?
* changes all syntactically top-level definitions to public?
* end result is not reindented
* consider additional testing of jell using other project source
* jackal
* jargon
* jog
* other?
* testing does not involve comparing "compilation" results of older
versions of jell with newer versions. this seems like it might be
a good thing to try.
* compare for identical source - sometimes one might expect the
same output (e.g. if performance was supposedly the only
difference).
* some source differences might be expected - e.g. if the
generated output no longer removed `import` forms but instead
wraps them in `(comment ...)`.
* import forms must not have whitespace or line comments before the
`import` symbol to be processed properly (at least by
`tweak-import-forms`).
* defining forms must not have whitespace or line comments before
the `def...`, `var...`, etc. symbols to be processed properly (at
least by `find-top-level-syms`).
* no proactive mechanisms for trying to warn about symbol
"collisions" between global names and names within quoted /
quasiquoted contexts (e.g. within pegs -- recall example with
`replace` in `jipper.janet`). see note elsewhere about recording
that one is within a quoted or quasiquoted form.
* there isn't yet a "study" mode that can signal the use of
constructs that are not supported (or potentially problematic).
such a mode could be used as a kind of a linter in ordinary
development to keep one's code in a shape that's more likely to be
reusable. it's likely to be a fair bit of work to create
something comprehensive all at once. it's probably worth having
some limited version at first and then gradually add to this over
time.
* not possible to execute single stage (e.g. just study or just
prepare or just link). this might be slightly tricky to do if one
just wants to operate on later stages because all of the needed
pieces may not be available?
* no option to remove "testing" comment forms (or all comment
forms?). may want to always keep this optional even if supported
eventually because the comment block tests being transformed along
with the code can be helfpul in some cases to detect whether the
transformation broke some of the code.
* not making "imported" definitions all private in starting file.
doing so could make the single file work nicely as just a library.
another option might be to prefix pervasively and add a bit at the
end of the file that explicitly defines some "export" names that
are not prefixed. these could be specified via configuration.
all other top-level definitions (except main?) might be made
private.
* not renaming things defined within comment forms
* only .janet files (no c). this limitation seems very unlikely to
be one that can be lifted.
* only handles input files that are siblings within the same
directory.
* only handling files with certain types of import forms (e.g. no
`require` forms or other non-import forms are handled). need to
spell out more clearly the constraints. should detect and warn.
* values for :as and :prefix which contain potentially problematic
characters (e.g. may be :prefix values should not have
slashes?). to do this, details of what is acceptable or not
acceptable need to be spelled out? probably want to stick with
a subset of characters that work for file paths on multiple
platforms? an example of a character to avoid might be "/"?
above may be "global" is meant and not necessarily "top-level"?
* renaming names within macro definitions may be naive. this may
need to be examined more closely but it isn't so pressing atm
because there are no macro definitions in the code being used for
exploration.
* candidates for an optional check phase - might start by writing
usages for jipper as experiments and if these work out, place in
an optional check phase for jell.
* not (yet) handling files with `use` forms. should detect and
warn?
* not (yet) handling code that uses `upscope` (and `compwhen`,
etc.). there is some similarity with the handling of "top-level"
definitions within `comment` forms, though it's not quite the
same. should detect and warn.
* no handling of defglobal or varglobal. they don't come up much so
not much of an issue? detect?
* no handling of defdyn?
* global definitions that have names that are prefixed are not
warned about. better to not support such names initially.
possibly in future.
* no support for arbitrarily nested global top-level destructuring
defines (don't do this in comment blocks either if the comment
blocks contain tests). probably could warn via an initial scan?
very simple things are supported (e.g. `(def [a b] ...)` or `(def
{:a a :b b} ...)`).
* not (yet) handling code that has a top-level definition that has a
name that collides with a non-top-level definition's name (at
least in the same file). can warn about this probably via initial
scan. the old jipper.janet had at least one of these
(`make-state`). more "shadowing detection" might be doable:
* checking names in argument tuples
* checking non-top-level definition names
* any other place that names might be introduced...
it may not be problematic for there to be a non-top-level
definition with name x preceding a top-level definition with
name x (so the jipper.janet case of `make-state` is fine).
the reverse case might be an issue though. however, it might
depend on whether all names are identified before any renaming
is attempted. perhaps better to arrange for renaming of
top-level names and their uses such that only "uses" that appear
later in the file are targets of renaming. perhaps having
available locations of definitions and uses would be a good
idea.
probably better to do the same within comment blocks too
(because of tests)?
* code that uses ordinary tuples (i.e. () vs []) for the parameter
portion of defn, defmacro, etc. is not warned about. probably not
worth supporting in the future because in practice almost no one
writes code like this?
* no warnings for macro definitions that lead to top-level
definitions + calls to such macros. possibly a fair bit of work
to pull off detecting.
* not (yet) handling shadowing of definitions (even between things
within `comment` forms and outside). is there really an issue /
limitation here? warn if a global definition within a `comment`
form "collides" with a non-comment global definition?
* not handling certain kinds of defining, e.g. like what spork's
path.janet does. the symbol renaming that might be needed seems
impractical? path.janet has defmacros that contain defs and
defns. the macros are used later in the file. possibly could
detect and warn? seems hard in general?
* "splitting" of file into modules isn't supported. possibly adding
comments in various parts could make splitting more tractable.
import forms that used to exist are now "(comment ...)"-ed so a
step has been made in this direction. this may make examining the
generated code when investigating issues a bit easier as well.
* "copy one file to install" approach not supported on windows
because no shebang-like mechanism (editing file type associations
doesn't count?). possibly have a way to generate a launcher file
(e.g. a "shim" `.bat` script) via a "one time" special execution
of the janet script (e.g. manually invoke `janet jell
make-launcher`).
* go through and try to merge items with various sections?
* "tree-shaking" -- by tracking which symbols are used in calls
(note: function names can be passed as parameters too!), it might
be possible to do this, but there is stuff like eval, macros,
etc. to contend with so may be not worth the trouble?
* not (yet) trying to handle unprefixing of top-level names being
defined within source files (this is different from prefixed names
that result from use of import). should detect and warn.
in the future might be nice to unprefix if possible. warn if not
possible. perhaps better to note it and avoid using the prefix
for other things?
this was an in issue in zipper.janet (used s/ prefix), but rewrote
to eliminate issue.
jeep has imports which have :as values that use slashes:
(import ./subs/install :as cmd/install)
possibly unprefixing these would be worth considering at some
point? but may be this is a slightly different issue?
possibly unprefixing overall can be avoided by choosing to use a
non-slash character instead of a slash as a separator between a
prefix and an existing name.
* terms with specific meanings -- more or less defined within the text
* starting file
* imported file
* input file
* prefix
* global name
* imported name
* domestic name
* revised version of "stages" idea
* check (optional)
run own checks (i.e. not janet -k) on source to generate warnings
about potentially problematic code.
generating a report of located constructs might be of interest
too? e.g. number of top-level definitions, comment forms, import
forms, etc.
keeping this stage independent means that one is not required to
pay the cost of checking, but one has the option to if desired.
* `use` forms not supported due to analysis depending on `import`
forms
* use of symbols in "data" (e.g. peg specials) may result in
renaming issues. e.g. suppose a file has a peg that uses the
`replace` peg special and further that the file also has a
function named `replace`. when renaming names in this file, the
`replace` in the peg may get renamed. this is undesirable.
would this type of situation always be "interior" to quoted or
quasiquoted content?
* potentially add things from the "warnings during study phase"
section and elsewhere.
* study
given a starting file:
1. perform some checking of the starting file
2. identify all relevant imported files and corresponding
prefixes.
step 1 might be done by running a linter on the starting file
before proceeding, but also may be run existing tests. if either
turn up issues, likely it's better to address those before
proceeding further.
step 2 is accomplished via a traversal that begins at the
starting file. as source is examined, `import` forms may be
encountered. each import form is analyzed to determine:
* a corresponding input file, which will be referred to as an
imported file
* a prefix for the corresponding imported file
each newly encountered imported file is then examined in turn and
the process continues recursively.
note that:
* a "starting file" is not an "imported file". the term "input
file" will be used to refer to either type of file.
* an imported file may be encountered more than once and for these
subsequent encounters, the imported file should not be
traversed. i.e. an imported file should only be traversed once.
* however, at each point of encounter of an imported file, the
specific prefix met should be noted as this may differ depending
on the specific import form (typically in different files
though). probably should warn / abort if different prefixes are
being used for the same file.
* for the moment, make use of the existing prefixes for renaming
purposes later.
* prepare
1. transform each one appropriately for the next stage
X. check transformed content a bit
step 1 is accomplished by first associating a unique prefix to
every imported file (but not the starting file) and then producing
modified versions of all of the identified input files.
the modifications consist of appropriately changing names in each
of the imported files (n.b. though only for "imported names" --
see below -- in the starting file) as well as import forms in all
input files (n.b. that includes the starting file):
* the first is done by creating new names for certain names that
appear in the file and then performing replacements where
appropriate.
* the second is done by modifying the import forms to use `:prefix
""` (or changing the `import` form to be a `use` form).
typically only some names in each imported file need to be changed
(e.g. local names are left alone). there are two sorts of names
that may need renaming:
* "domestic names", i.e. those that are "defined" in the current
file.
relevant locations for changing a domestic name include
"definition site" and all "use sites" (e.g. calls or being
passed as arguments).
* "imported names", i.e. those that are "imported".
each imported name will be assumed to have some existing prefix.
the presence of a prefix indicates that a name is imported and
further, the particular prefix uniquely determines which file
the name originated from. previous analysis of import forms
should have made it clear which prefixes are associated with
which files.
the existing prefix (and separator character, e.g `/`) should be
removed and replaced with a newly chosen prefix corresponding to
the file from which the name is imported (plus possibly a
different separator character, e.g. `^`). there should only be
"use sites" (no "definition sites") for imported names and those
should be renamed.
performing the name replacements will initially be done using
multiple passes in order to keep tractability under control and
increase correctness.
* there will be at least one initial pass to determine which
identifiers need to be renamed.
there could be a pass for domestic names that involves examining
where they are defined. there are plain top-level names which
might be handled in one pass and then there are "top-level"
names within comment forms which could be handled in a separate
pass though possibly better to not do initially. names defined
within `upscope` and friends might not be handled initially.
might want to warn / abort if plain top-level names suggest
shadowing / duplication. however, due to the way comment form
tests are written, shadowing / duplication should probably be
allowed (within a file).
there could be a pass for imported names which involves
examining import forms to identifiy relevant prefixes. for
imported names, there could be a separate pass for names within
comment forms. in any case, what is identified is a set of
prefixes which could then be used during traversal (in a later
pass) to determine if some encountered idenitifier is imported
or not and hence whether it should be renamed.
* there may be one or more subsequent passes to actually carry out
the replacements.
possibly one for plain top-level global names. perhaps a
separate pass for "global" names defined within comment forms.
again, names that were introduced within `upscope` and friends
may not be supported initially.
step X. might be done by running a linter across the products. if
the comment-form style testing method is in use, those tests ought
to have been transformed appropriately as well so running them to
check on behavior might be a good idea too.
note that the transformed versions of the input files should still
function together and produce the same results as for the original
input files. (though it seems possible that some kinds of
self-referential operations might produce different behaviors.
may be there are other such kinds of "exceptional" behavior as
well?)
* link
given transformed input files from previous stage, produce final
product out of the inputs:
1. bring together the modified input files' contents (from the
previous stage) appropriately
2. deactivate each of the pre-existing import forms
X. check final product a bit
step 1 is currently done by visiting top-level forms one at a time
starting with the modified start file and following relevant
modified imported files via import forms.
step 2 is accomplished by commenting out import forms.
step X might be done in a manner similar to that of the previous
prepare stage, i.e. running a linter and any included comment-form
tests.
* on the necessity of renaming certain names and the terms / phrases
"prefixing", "imported names", "domestic names", and "global names".
* since content from multiple files is being brought together into a
single file, renaming is needed to avoid "collisions" between
instances of certain names being used differently among two or
more files, e.g.
file x:
(def a 1)
file y:
(def a 2)
combined file:
(def a 1)
(def a 2) # oops
"prefixing" of names with `<something>/` is one way of renaming,
e.g.
combined file:
(def i/a 1)
(def j/a 2) # no collision now
prefixing can be done using characters other than slash,
e.g. `<something>^` seems like it could work too.
combined file:
(def i^a 1)
(def j^a 2) # no collision now
postfixing might be another possibility.
combined file:
(def a^i 1)
(def a^j 2) # no collision now
fwiw, prefixing with slash is already what happens when janet
applies `import`, e.g. suppose there's a file with content:
# assume there is a file `my-fun.janet` in the same directory
(import ./my-fun :as mf)
then public top-level definitions from `my-fun.janet` will be
available but via names that begin with `mf/`. so if
`my-fun.janet` has content:
(def j 8)
then within the file with the `import` form from above (assuming
no other arrangements), `mf/j` will evaluate to `8`.
* for a given name which requires renaming, it needs to be renamed
where it is defined ("definition site") as well as where it is
used ("use site"), e.g.
before renaming:
(defn f [x]
(if (zero? x)
0
(+ 1 (f (dec x)))))
(f 2)
after renaming:
(defn a^f [x]
(if (zero? x)
0
(+ 1 (a^f (dec x)))))
(a^f 2)
* in the most general case, the names which require renaming are
those that are "global", i.e. those that can be used from any scope
(though shadowing might add some nuance).
constructs such as `defglobal`, `varglobal`, and `eval` can
introduce global names dynamically and are thus not generally
amenable to syntactic methods. in short, they won't be supported
fully and likely not at all initially.
syntactically there are at least three cases that might be worth
supporting.
* plain top-level definitions, e.g. `a` and `main` in:
(def a 8)
(defn main
[& args]
(print a))
* names that are defined within the "top-level" of a use of
`comment`, e.g. `a` in:
(comment
# top-level within `comment`
(def a 1)
# top-level within `comment`
a
# =>
1
)
the reason this type of name is being considered is to support a
certain type of testing convention.
* names that are defined within the "top-level" of a use of
`upscope` (or a few others, see later), e.g. `b` in:
(upscope
# top-level within `upscope`;
(def b 2)
)
# `b` can then be used as if defined at the syntactic
# top-level
(pp (inc b))
note that `compwhen` also ends up using `upscope`. `compif` and
`comptime` achieve a similar end via `eval`.
although one can write:
(eval (def a 1))
and end up with `a` defined at the top level, this is doing
something different than:
(eval '(def a 1))
`eval` is a function and its argument expressions are evaluated
at the scope the expression is in.
all functions have this behavior, but special forms and macros
only sometimes. i.e. at the top-level, when a function
evaluates its argument expressions, those expressions are
evaluated at the top-level.
more generally, the argument expressions are evaluated in the
current scope(?).
perhaps in the future some of these could be warned about...
or handled?
* there are other names that may not need to be renamed from the
perspective of "merging" file content together. some of these
include:
* names introduced via parameter tuples, e.g.
(defn my-fn
[a-name b-name]
8)
`a-name` and `b-name` are local to `my-fn` and thus should not
be affected by "merging".
* non-top-level names introduced by `def`, `let`, etc., e.g.
(defn my-other-fn
[x y]
(def a 1)
(let [b 2]
(+ a b)))
`a` and `b` are local to `my-other-fn` and thus should not
be affected by "merging".
* are there any other kinds of names that would be unaffected?
* the names that need to be renamed and those that don't need to be
renamed (because of merging concerns) might overlap
(e.g. shadowing) in some cases, e.g.
(def a 1)
(defn f
[x]
(def a 2)
a)
there is a top-level `a` and a local `a` that have the same name.
from the perspective of program transformation, it would probably
make things easier if this kind of situation did not arise. if
practical, it might be nice to detect if there are any instances
in the code about to be manipulated and give appropriate feedback
and/or abort processing.
* some names within a file become "available" via the use of a
construct like `import`. these will be referred to as "imported
names". the names within a file which are defined within the file
will be called "domestic names". the distinction is made partly
to improve thinking and communicating about renaming.
for a given file, renaming the domestic names involves all three
types of global names. for imported names, only the plain
top-level and upscope types of top-level names are the target of
renaming, i.e. global top-level names within comment forms from
another file aren't supposed to be visible outisde of the files
they are defined in.
* constructs that introduce names apart from what has been
mentioned elsewhere...
* parameter tuples
* straight-forward macros
* single name that is easy to detect
* label, with, when-with, if-with, forv, for, as->, as?->,
ffi/defbind-alias, ffi/defbind
* possibly multiple names, but no destructuring
* catch
* possiblly multiple names that might get complicated because of
destructuring
* each, eachk, eachp, let, if-let, when-let
* complicated (but all the same?)
* loop, seq, catseq, tabseq, generate
* most complicated?
* match
* user-defined macros
* provide hooks for handling these - definitely not at first
* this might allow handling of things like path.janet
eventually
* other things which are not relevant?
* names introduced but typically used like ,name
* with-syms
* involves keywords so not needed?
* prompt, with-dyns, with-vars
* is it practical to detect shadowing? it is related to the
"constructs that introduce names" items and as such a better
question might be "how much shadowing would be practical to
detect?".
* misc notes
* organizational challenge of too many notes. perhaps making a
section of "may be later" items would help declutter a bit.
* may be unprefixing can be avoided entirely by using a non-slash
(and non-problematic) separator character. ^ is not used very
much atm (according to some research). as mentioned elsewhere may
be better to allow customization.
unprefixing can't really be avoided for imported names which
typically will have some prefix determined by a corresponding
import form.
* zipper editing does not update location information though
multiple edits appear to be supported (see modify-test.janet).
modifications should then be made after all location information
has been obtained and utilized?
* consider the idea of "normalization" (of source) being applied to
simplify later manipulation (in the context of the "stages"
mentioned elsewhere). an example is: `(import ./hello)` could be
re-expressed as `(import ./hello :as hello)` or `(import ./hello
:prefix "hello")`. however, for this specific case, if `import`
forms are going to be commented out anyway it seems rather
pointless. normalization might be good for other situations
through.
* handy to be able to determine whether a given form is at the
top-level (or within `comment`, `upscope`, etc.)? this might be
relatively straight-forward by using `path` and `leftmost`.
* handy to be able to find the first non-whitespace / non-comment
element of an indexed-type or a dictionary. right-skip-wsc
doesn't check the current location so that needs to be checked
beforehand.
* any use in a self-extraction step for native and other
(e.g. resources) bits?
* on various approaches to carrying out renaming
* one possible way of actually performing the name replacements is
to determine what all of the names are that need changing via an
initial pass and then making a subsequent pass to actually change
the target names.
* another approach might be to scan for a name to change, remember
the current location, make the name change in subsequent locations
in the file, return to the remembered location, and then to
continue scanning for another name to change and repeat as before.
this approach might be conceptually simpler at the cost of a fair
number of traversals.
* a third approach is to carry out identification of names as well
as renaming in a single pass. this may be the most efficient
approach, but it may also be more complicated to get right as well
as maintain and/or modify.
in terms of simplicity and getting things correct / working,
probably taking a multi-pass approach makes the most sense at least
initially.
* notes on specific renaming cases
* forms like ->, ->>, etc. can contain function names in
argument positions
* similar remark for map, filter, etc.
* macro definitions may also contain things? possibly these
are harder to detect? better to examine some actual
cases:
(defmacro toggle
"..."
[value]
~(set ,value (,not ,value)))
things prefixed with `,` will be within :unquote nodes?
* any other "macro reader" things to be concerned with?
* :fn?
* :quote?
* :quasiquote?
* :splice?
* any other cases?
* overall approach notes
* try breaking up bin/jog into files, then make modifications until
"original" files are "recovered". take notes in the process.
this approach was followed at least for part of the overall
development activity.
* studied bin/jog's current form and compared with the files it
was built out of to see what changes were needed.
* "doctored" files that jog can be built from:
* args.janet - a
* completion.janet - c
* jipper.janet - j
* location.janet - l
* search.janet - s
* report.janet - r
* search.janet
* find.janet
* find.janet - f
* location.janet
* jipper.janet
* main.janet (don't prefix anything in this file...has main)
* args.janet
* completion.janet
* report.janet
* figure out what "doctoring" is needed to arrive at files in their
forms above. manually create versions of files that would have
existed before doctoring and then compare.
* collisions between the peg name "replace" and jipper's "replace".
in general, it won't be possible to avoid these kinds of collisions
as janet's peg system might gain new specials.
in general, some kind of detection / warning seems desirable
* try to detect whether something is a peg or other kind of data
containing symbols? or is it better to not replace symbols
within quoted or quasiquoted things? may be emit warnings if
quoted / quasiquoted stuff is being modified? still need some
way to indicate what to do in such a case to avoid manual
intervention every time.
* don't use `replace` in the peg.
* could use `/` instead, but this won't work in general because
not every peg special has an appropriate abbreviation.
* define something to have the symbol `replace` as its value
and unquote it into place:
(def rpl (symbol "replace"))
(peg/match ~(,rpl "a" "b") "a")
this approach could work, but it would be better if potential
issues could be warned about so the code could get rewritten
appropriately.
went with this approach for the moment and may work on trying to
figure out how to warn.
* if the symbol renaming was slightly smarter in not blindly
renaming all seemingly matching symbols through the entire file,
this particular problem could have been avoided because the
affected `replace` occurred before the definition of the
function `replace`.
doesn't seem likely that code could be written to accomodate in
all cases though.
* changing jipper's api might work, but issues could arise later
if peg/match is enhanced. however, at this point it seems
unlikely that much would get added to peg/match?
* mark with special comment. this provides a finer-grained way of
indicating something that shouldn't be changed, even within a
function body that has other parts that need modification.
some downsides to this approach include a more complex
implementation as well as potential slow-down for lots of
checking.
* try to design comment to be obviously showing certain intent
and be unlikely that people will create by accident.
* check out how clj-kondo does things:
https://cljdoc.org/d/clj-kondo/clj-kondo/2025.07.26/doc/configuration#ignore-warnings-in-an-expression
#_:clj-kondo/ignore
(inc 1 2 3)
#_{:clj-kondo/ignore [:invalid-arity]}
(inc 1 2 3)
* place a special comment (directive) "nearby" candidates:
* before - it's what clj-kondo does and comments tend to come
"before" what they comment on...though there are
"trailing" comments too
* cannot put on same line as item that is being referred to
because janet only has line comments (no equivalent of #_)
* cannot put before first line if file is a shebang script
because the shebang line must be first
* after - seems different from what might be expected.
* can put after first line
* can put on same line as thing it refers to
(replace #< :jell/no-rename
...)
* either side - flexible but complex
#> :jell/ignore
fun
bubbly #< :jell/ignore
use angle bracket to indicate which direction item being
referred to is located?
* may be helpful to have left-skip-ws and right-skip-ws to be
able to move to comments (similar to left-skip-wsc and
right-skip-wsc except doesn't skip comments)
* general patching mechanism that is applied after the prepare
stage completes?
patches might need to be updated due to underlying source
changes, but this approach might not be a bad compromise,
e.g. compared to trying to support some kind of directive system
which might make things more complicated and slower.
* marking definitions with metadata to flag as "don't rename in
here"? might work for simple cases? won't work for this case
because there is something within the function definition that
needs to be modified -- specifically, `make-attrs` needs to be
renamed.
* observations from rewriting bin/jog to use prefixed identifiers that
reflect which file they might have originated from
* renaming some function names within ->, ->>, -?>, and friends
is more work because of things like:
(->> (map + [1 2 3])
invert)
i.e. not all function names appear as first elements of tuples.
want to handle this.
* functions being passed as arguments, like for map, filter, etc.
can probably be handled, though unclear whether trying to handle
this will accidentally rename things in cases where there is a
tuple that isn't a call...want to handle the ordinary case.
* in the old `zipper.janet` file there is a local function named
`make-state` and a top-level function of the same name. may be
don't want to rename the local one. how to tell apart the
uses...need to track scope? better to have the limitation to not
allow the same name for top-level and internal things? (change
code in `zipper.janet` to not have this characteristic -- did
this) or at least warn if detected?
* probably do want to "prefix" "top-level" things within comment
blocks so that:
* tests from one file do not collide with test from another file
* tests run after "compilation"
* trickier to rename destructure-defined things, e.g.
(def [a b] [1 1])
as:
(def [z/a z/b] [1 1])
perhaps tuple case is relatively straight-forward? except
recursion...struct case is more complicated...may be better to
rewrite code to not use these constructs. could probably warn.
* import forms and the identifiers that use them (see
loc-jipper.janet for examples) seem not straight-forward to handle
in terms of renaming. is this referring to the content of comment
blocks?
(comment
(import ./location :as l)
(l/gen ...)
)
* zipper.janet and loc-jipper.janet are kind of weird birds...the
latter kind of redefines stuff from the former...can this be
avoided or reworked somehow to begin with (before trying to
process them with highlander)? zipper.janet and loc-jipper.janet
have been merged as jipper.janet to avoid this issue.
* possibly by warning of various issues, could support the idea of
having "patches" that are manually constructed by the author and
can be applied automatically upon each rebuild?
* linter (janet -k) seems pretty good at finding spots that
need renaming (outside of comment blocks)
* name ideas
* jell (current choice)
* highlander (jaylander or jighlander)
* joust (only one remains after?)
* chimera (collection of different things)
* article (a, an, the -> one)
* single
* assimilator, absorber
* old planning notes for related idea of doing use -> import
rewrite below
# 0. parse all files to find all symbols?
# * will use in process of choosing appropriate alias...
# this might be relevant because someone might
# do `(defn my/name [] ...)` so we'd want to avoid
# choosing `my` as an alias.
#
# 1. find all definitions across all files
# * require that all relevant files be specified? or can
# the code make an attempt to manually located "installed"
# code? may not work for things defined in .c files...
# * what about things defined in .c? possibly could work
# if source is available.
#
# 2. find all `(use ...)` forms in all files
#
# 3. replace each `(use ...)` form with appropriate `(import ...)` form
# * avoid alias (i.e. `:as <name>`) collisions
#
# 4. find all uses of things brought in via `use`
# * check all symbols in file for potential matches
# * edge case when later `(use ...)` overrides earlier one.
# * try to identify potential "clashes" earlier in process,
# e.g. after enumerating all symbols across all files
* janet flavor limits
* all input files must be siblings (no files in subdirectories),
i.e. no "multilevel" paths. the `./dir/init.janet` type of import
is not supported (i.e. `(import ./dir)`).
* all import paths must start with `./`, i.e. no syspath files,
working directory imports (e.g. the paths start with `/`), and
`@-prefixed imports are not supported. only .janet files in same
directory as start file.
* import forms with :export true are not supported
* import forms with :only are not supported
* import forms must use :as or :prefix, i.e. a prefix must be
explicitly specified. something like `(import ./alpha)` is not
currently supported.
* the prefixes defined by :as and/or :prefix must be consistent
across files, i.e. if there is `(import ./mine :as m)` somewhere
then all other instances of `(import ./mine ...)` needs to use
`m`.
* continue filling stuff in here
* undocumented features
* env var VERBOSE can be used to dump some output during
execution. possibly useful for investigating issues.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment