Last active
December 8, 2025 04:31
-
-
Save sogaiu/36d04c3f33dbc56461bcd16fbfe57b73 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| * code to help with "compiling" / "cat-ing" multiple files into a | |
| self-contained single script | |
| * develop with files split, but "compile" to single script | |
| * "include" files that have their "effectively" top-level | |
| definition names (and uses) renamed to use `<ns>/` as a prefix. | |
| more detail elsewhere in document. | |
| * remove certain import forms from "main" script | |
| * rationale | |
| * single file can be copied and used more easily as a script or | |
| library | |
| * easier to "vendor" into projects | |
| * simple version of "stages" idea | |
| * prepare | |
| given a starting file: | |
| 0. perform some checking of starting file | |
| 1. identify all relevant input files and the order in which their | |
| modified counterparts need to be concatenated in the next stage | |
| 2. transform each one appropriately for the next stage | |
| X. check transformed content a bit | |
| step 0. 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 1. is accomplished by a traversal that begins at a starting | |
| file. `import` forms are analyzed to determine other files which | |
| are "followed into" and the process continues recursively. as a | |
| side effect, this step also identifies the order in which the | |
| modified content should be concatenated together in the next | |
| "assemble" stage. | |
| step 2. is accomplished by first associating a unique prefix to | |
| each file and then producing modified versions of the input files | |
| determined in the previous step. | |
| the modifications consist of: | |
| * appropriately changing names in each of the input files. this | |
| is done by creating new names by prepending prefixes to relevant | |
| existing names. | |
| * modifying the associated `import` forms to refer to the | |
| corresponding prefixes | |
| typically only some names in each file need to be changed | |
| (e.g. local names are typically left alone). relevant locations | |
| for changing a given name include definition "site" and all use | |
| "sites" (e.g. calls or passing as arguments). | |
| 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. well, mostly -- excepting things like self-analyzing | |
| and other such self-referential bits. | |
| * assemble | |
| given transformed input files from previous stage, produce final | |
| product out of the inputs: | |
| 1. concatenate together the modified input files' contents (from | |
| the previous stage) in an appropriate order | |
| 2. remove or comment out each of the pre-existing import forms | |
| X. check final product a bit | |
| 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", "external names", "internal names", and "effectively | |
| top-level" | |
| * 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 as well as where it is used, 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) | |
| * there are at least three sorts of names that may need to be | |
| renamed. | |
| only one is syntactically "top-level", so the phrase "effectively | |
| top-level" will be used to mean all three: | |
| * 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`, 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`. what about | |
| `compif` and `comptime`? | |
| * 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 "external | |
| names". the names within a file which are defined within the file | |
| will be called "internal names". the distinction is made partly | |
| to improve thinking and communicating about renaming. | |
| for a given file, renaming the internal names involves all three | |
| types of effectively top-level names. for external names, only | |
| the plain top-level and upscope types of top-level names are the | |
| target of renaming, i.e. effectively 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 the effectively | |
| top-level things 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 | |
| * use leftmost and path for ascertaining whether in comment or | |
| upscope or ? | |
| * that jeat doesn't look in `( comment ...)` or `(#\ncomment ...)` | |
| can be seen as a feature, as those can be quick ways to | |
| disable an entire comment form worth of tests? | |
| * organizational challenge of too many notes. perhaps making a | |
| section of "may be later" items would help declutter a bit. | |
| * self-extraction step for native and other (e.g. resources) bits? | |
| * 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. | |
| * apply zippers for analysis and other tasks | |
| * 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 effectively top-level)? | |
| * top-level - use j/up on a zipper created using zip-down and | |
| check the node type. if it's :code, then the zipper was at the | |
| top-level. | |
| * top-level of top-level comment - j/up is a comment form and j/up | |
| one more has node :code. | |
| * top-level of upscope - similar to comment, but need to also | |
| ensure the upscope is "positioned" to allow top-level | |
| definitions to occur. for example, if at the top-level, one | |
| evaluates `(do (upscope (def a 1)))`, this won't result in `a` | |
| being defined at the top-level. | |
| * 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. | |
| * limits and questions | |
| * 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. | |
| * only .janet files (no c). this limitation seems very unlikely to | |
| be one that can be lifted. | |
| * only handle input files that are siblings within the same | |
| directory initially. related to "relative paths that are single | |
| level" mentioned in import form limitations. | |
| * only handling files with certain types of import forms. need to | |
| spell out more clearly the constraints. should detect and warn. | |
| * only relative paths that are single level (e.g. ./ok is fine but | |
| not ./this/is/not/ok). also "directory with init.janet" types | |
| of imports are not handled either. | |
| * might not handle arbitrary characters in :as / :prefix values, | |
| e.g. may want to avoid "/". | |
| * within the same file, two import forms should not use the same | |
| :as / :prefix value. jeat/to-test.janet has an example where | |
| this is done. | |
| * if there is no :as or :prefix, rewrite the form to use one or | |
| the other (normalize?) | |
| * :only is not handled | |
| * :export true is not handled | |
| * 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. jipper.janet may have one of these (`make-state`). | |
| effectively 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. | |
| * not (yet) handling files with `use` forms. should detect and | |
| warn? | |
| * not (yet) handling shadowing of definitions (even between things | |
| within `comment` forms and outside). is there really an issue / | |
| limitation here? warn if an effectively top-level definition | |
| within a `comment` form "collides" with a non-comment effectively | |
| top-level definition? | |
| * not (yet) handling import forms that span multiple lines. can | |
| probably use zippers to overcome this later if needed. don't | |
| recall having seen an import form across multiple lines. could | |
| probably detect and warn. | |
| * not (yet) handling code that uses `upscope`. 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. | |
| * 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? | |
| * no effectively top-level destructuring defines (don't do this in | |
| comment blocks either if the comment blocks contain tests). could | |
| probably support this eventually. probably could warn via an | |
| initial scan? possibly support very simple things first such as | |
| flat tuples? | |
| * the first non-whitespace / non-comment "thing" after a defining | |
| symbol (e.g. def, def-, defn, etc.) is one of: | |
| * symbol - most common | |
| * tuple or array - destructuring | |
| * struct or table - destructuring | |
| the content of the indexed type / dictionary can be arbitrarily | |
| nested though it rarely is something more than a single level? | |
| can probably do a "query" to assess this. | |
| * no handling of defglobal or varglobal. they don't come up much so | |
| not much of an issue? detect? | |
| * no handling of defdyn? | |
| * stages (seems like there are three at this point) | |
| * "analysis" - determine if some preconditions are not met and/or | |
| warn of use of certain constructs? would be nice to be | |
| comprehensive in checking, but this might be quite a lot of work. | |
| try to figure out what is essential and what might be postponed. | |
| see limits described elsewhere for candidates of what to check for | |
| and create list of things to check: | |
| * running through a linter (e.g. janet -k) before attempting | |
| anything else seems worthwhile. | |
| * punt on warnings initially -- see may be later section | |
| things to do in preparation for the next stage: | |
| * identify all relevant input files (traverse import form paths | |
| starting at the starting file?) | |
| * identify files that have import forms in them and those that | |
| don't. record the details (e.g. file a imports b and c using | |
| such and such aliases). | |
| * verify that all input files are siblings in the same | |
| directory? | |
| * as a side-effect of this process, the order in which files | |
| need to be "joined" / "concatenated" in the final stage can be | |
| identified (the traversal order). | |
| * settle on prefix names | |
| * one idea is to sort the list of import paths first (longest | |
| first, then lexicographically). try successively longer | |
| substrings of each filename. try to detect if unsuccessful. | |
| * even simpler would be to just start at "a" and proceed up | |
| through "z", then consider using capital letters, etc. | |
| could eventually allow user to specify a mapping of file names | |
| (or paths in the future?) to aliases as well. | |
| * find definitions and uses and produce a summary? | |
| possibly one could generate some kind of "data" that describes | |
| all changes needed in the next ("prepare inputs") stage? may be | |
| the following stage or stages can be all about just "realizing" | |
| (via execution?) the described changes? | |
| * seems non-trivial to express multiple changes because one | |
| change might refer to location x, which one performed might | |
| affect locations of subsequent changes. | |
| * other things? | |
| should "analysis" results be written out in some file that can be | |
| used by next stage? | |
| * "prepare inputs" - generate new files from source files such that | |
| they are ready for the "assemble" stage. | |
| since the content of all of the input files will end up in the | |
| same destination file, some renaming is likely needed for names in | |
| each of the input files. the renaming should be such that for | |
| each relevant name: | |
| 1. the new name should end up referring to what the old name | |
| referred to before the renaming, and | |
| 2. the new name should not "collide" with any other name from | |
| input files (other ones as well as ones from the file the | |
| original name was from) | |
| for point 1, each effectively top-level defintion needs to change | |
| as well as each use of such names. | |
| for point 2, in a previous stage appropriate prefixes should have | |
| been generated for each input file so this prefix (+ a separator | |
| character) can be prepended to each name to avoid collisions. | |
| * two kinds of files to operate on: | |
| * no import forms | |
| * prefix all: | |
| * effectively top-level definition names and | |
| * associated uses determined for this file | |
| there should be no effectively top-level definitions that | |
| have prefixed names based on having passed the previous | |
| stage. | |
| * there are three types of effectively top-level | |
| definitions, but initially only handle plain and those | |
| within `comment`. finding these two types seems | |
| straight-forward. for each found name record: | |
| * name - used for identifying what to rename (but also | |
| whether it collides with an existing definition?) | |
| * location - may matter when figuring out what counts as a | |
| use. only later locations in the file count as uses? | |
| * def type (e.g. def, defn, etc.) - not sure if this is | |
| needed, but store anyway? | |
| * finding uses of top-level definitions seems | |
| straight-forward (as long as there is no clashing / | |
| shadowing going on). may be a simple depth-first search | |
| through the whole tree is sufficient? though is it | |
| possible that some symbols found this way could be false | |
| positives? yes, if someone has used the name of a | |
| callable as the name of a variable, for example | |
| (i.e. shadowing). might be other cases too. | |
| when looking for uses of effectively top-level definition | |
| names within `comment` forms, only forms within `comment` | |
| forms should be considered. these names should not leak | |
| "outside" of comment forms (though they can be defined in | |
| one comment form and be used in another). | |
| * at least one import form | |
| * check import forms for use of :as / :prefix. use results to | |
| identify which names in file are names from elsewhere, i.e. | |
| "external" names. rename the determined "external" names | |
| using the new names established via prefixing and update if | |
| needed the corresponding import form. for example: | |
| (import ./args :as arg) | |
| (def b arg/fun) | |
| might become: | |
| (import ./args :prefix "") | |
| (def b a/fun) | |
| assuming "a" was chosen as the prefix for args.janet, and at | |
| some point effectively top-level definition names in | |
| args.janet and uses are renamed to have the prefix "a". | |
| alternatively, rewriting using `use` might work? | |
| (use ./args) | |
| (def b a/fun) | |
| may be rewrite `(import ./some-path)` as either `(import | |
| ./some-path :as some-path)` or `(import ./some-path :prefix | |
| "some-path")`? some kind of "normalization"... | |
| * the above bits are needed in addition to the processing | |
| that is necessary for the "no imports" case. | |
| after generating the new files, might be good to run tests. could | |
| compare the number of tests in the input files with the number in | |
| the final result. probably want the number of passed tests to | |
| match. | |
| * "assemble" - final stage is the recursive minimal concatenation of | |
| the files prepared in the previous stage. i.e. basically | |
| concatenating in the right order but only doing each "included" | |
| file once. a preliminary implementation of this portion has been | |
| made by(modifying judge-gen's build.janet. | |
| * optionally the resulting file can be run through some kind of | |
| indenter / formatter. | |
| * might be good to run tests. could compare the total number of | |
| tests in the input files with the number in the final result. | |
| * optionally provide way to strip out comment blocks. this can | |
| reduce the final size of the file but at the cost of removing | |
| tests. | |
| * 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? | |
| * 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 zipper.janet there is an internal function named make-state and | |
| a top-level function of the same name. may be don't want to | |
| rename the internal 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) 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? | |
| * after renaming, want to reindent? | |
| * linter (janet -k) seems pretty good at finding spots that | |
| need renaming (outside of comment blocks) | |
| * 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. | |
| * may be later | |
| * warnings during analysis phase: | |
| * warn if the separator character (default ^) is in use in any | |
| symbol name? possibly it's a non-issue. mull over. | |
| * warn of effectively top-level definition names that collide with | |
| non-top-level definition names or other names (in the same | |
| file). | |
| more generally(?) name collision / shadowing detection? | |
| * 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)? | |
| * warn of `import` forms that might be problematic. | |
| * simplest acceptable case is something like `(import | |
| ./some-path :as sp)` or `(import ./some-path :prefix "sp")` | |
| * the path portion needs to start with `./` | |
| * the path portion should not be "multi-level", e.g. | |
| things like `./this/is/not/ok` are out-of-scope atm | |
| * "directory with init.janet in it" type of import is not | |
| supported either. | |
| * so syspath, working directory, and @-prefixed imports are | |
| not supported. | |
| * things that probably should cause halting of processing: | |
| * :export true (does anyone use `:export false`?) | |
| * non-relative import paths | |
| * "multi-level" import paths | |
| * values for :as and :prefix which contain potentially | |
| problematic characters (e.g. may be :prefix values should | |
| not have slashes?) | |
| * warn of import forms in the same file that use the same value | |
| for :as or :prefix. note that one could be specified with :as | |
| and another with :prefix so "cross-comparison" is needed. | |
| * warn of top-level definitions that have names that are prefixed. | |
| better to not support such names initially. possibly in future. | |
| * warn of `use` forms. possibly allow in future. | |
| * warn of top-level destructuring defines. probably better to do | |
| the same within comment blocks too (because of tests)? may be | |
| support in future -- because of use in tests in comment blocks. | |
| simple destructuring may be relatively easy to support | |
| (e.g. flat tuples), but arbitrarily recursive destructuring may | |
| be too involved? | |
| * warn of import forms that span multiple lines. possibly could | |
| support in future. | |
| * warn of code that uses ordinary tuples (i.e. () vs []) for the | |
| parameter portion of defn, defmacro, etc. probably not worth | |
| supporting in the future because in practice almost no one | |
| writes code like this? | |
| * warn of defining like is done in path.janet. not sure if this | |
| is worth it...look for defmacros that contain def, defn, | |
| etc. along with actually calls to such macros? quite a bit of | |
| work to do? | |
| * other things to warn about? | |
| * replacing import lines with commented versions in appropriate | |
| locations turns out to be a bit trickier than expected. an | |
| alternative approach is to have an initial pass that comments them | |
| out with a special marking and then look for these "special" | |
| import lines during "compilation". not sure if it's worth it at | |
| this point. | |
| inserting `comment` at the beginning of an import form or putting | |
| a single quote in front of the import tuple would work if the | |
| import form is a top-level form. | |
| non-top-level import forms seem like they could be more work to | |
| handle. punt for now, but detect and warn? | |
| * providing a way to strip out comment blocks. 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. | |
| * make the single file work nicely as just a library. selectively | |
| prefixing might have been a way to do this but it seems | |
| complicated. | |
| 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. | |
| * maintain enough information within result to make "splitting" | |
| easier later. possibly adding comments in various parts could | |
| make splitting more tractable. | |
| * "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. | |
| * considered but have not yet pursued | |
| * make simplified sample files to help sketch out necessities? | |
| * phases idea | |
| * similarity to compiler phases | |
| * start at end at work backwards to come up with phases? | |
| * possible to have a zipper-like api on top of just an ordinary | |
| nested data structure of janet bits? not so easy? | |
| * 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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment