On this page:
4.1.1 Basic Source Operations
source?
unmodified-source?
file-source?
file-source
string-source?
string-source
modified-source?
modified-source
source-name
source-path
source-directory
source-original
source->string
with-input-from-source
4.1.2 Parsing, Expanding, and Compiling Sources
source-read-language
source-read-syntax
source-expand
source-can-expand?
source-text-of
source-comment-locations
9.2

4.1 Source Code🔗ℹ

 (require resyntax/grimoire/source) package: resyntax

In Resyntax, source code refers to source? values, which come in three types:

  • Source files, constructed with file-source, which don’t contain the code directly but refer to it by a local filesystem path.

  • Source strings, constructed with string-source, which contain the source code directly as a string and don’t exist anywhere on the local filesystem. (These are useful for testing Resyntax, and other scenarios where Resyntax needs to operate on code that doesn’t exist on disk.)

  • Modified sources, constructed by passing another (unmodified) source to modified-source along with a string representing what to replace the source’s contents with. A modified source contains both its new updated contents and a reference to the original source.

Resyntax’s basic architecture is to recursively take sources of any kind as input, produce modified-source? values as output, then re-analyze the modified sources again until no further modifications are desired. Then, Resyntax decides whether to commit those final modifications to the filesystem (as in resyntax fix) or merely display them to users (as in resyntax analyze). This recursive loop approach allows Resyntax to "look ahead" and produce a stack of dependent changes to commit in series without actually mutating the files on disk.

4.1.1 Basic Source Operations🔗ℹ

procedure

(source? v)  boolean?

  v : any/c
A predicate that recognizes source code values of any kind — file, string, or modified.

procedure

(unmodified-source? v)  boolean?

  v : any/c
A predicate that recognizes source code values that are not modified sources, i.e. either file sources or string sources.

procedure

(file-source? v)  boolean?

  v : any/c
A predicate that recognizes (unmodified) source files.

procedure

(file-source path)  file-source?

  path : path-string?
Constructs a source file that refers to the code stored on disk at path. The path is normalized with simple-form-path upon construction.

procedure

(string-source? v)  boolean?

  v : any/c
A predicate that recognizes source strings.

procedure

(string-source contents)  string-source?

  contents : string?
Constructs a source string containing contents directly.

procedure

(modified-source? v)  boolean?

  v : any/c
A predicate that recognizes modified sources. A modified source is always a wrapper around an unmodified source plus a string containing the full replacement text that the modified source should contain instead of what the original source contains.

procedure

(modified-source original new-contents)  modified-source?

  original : unmodified-source?
  new-contents : string?
Constructs a modified source that replaces the contents of original with new-contents. This represents a whole-file replacement — the complete contents of original are entirely swapped out with new-contents. Modified sources cannot represent partial edits on their own.

procedure

(source-name code)  (or/c path? symbol?)

  code : source?
Returns a name identifying code, suitable for use as a syntax object’s source location name. For file-based sources this is the source file’s path, and for string-based sources this is the symbol 'string. Modified sources always have the same name as their original unmodified sources.

procedure

(source-path code)  (or/c path? #false)

  code : source?
Returns the filesystem path of code, or #false if code is not file-based. Modified sources are file-based if their original source is file-based.

procedure

(source-directory code)  (or/c path? #false)

  code : source?
Returns the directory containing code, or #false if code is not file-based. Modified sources are file-based if their original source is file-based.

procedure

(source-original code)  unmodified-source?

  code : source?
Returns the original, unmodified source underlying code. If code is already unmodified, it is returned as-is.

procedure

(source->string code)  immutable-string?

  code : source?
Returns the full text of code, reading it from the filesystem if necessary. For modified-source? values, this returns the new, updated text rather than the original unmodified text.

procedure

(with-input-from-source code proc)  any

  code : source?
  proc : (-> any)
Calls proc with current-input-port set to a freshly opened input port reading the contents of code. For unmodified file sources, this opens a file port. For modified sources and string sources, this opens a string port without interacting with the filesystem.

4.1.2 Parsing, Expanding, and Compiling Sources🔗ℹ

The following operations allow treating source code values as inputs to Racket’s compiler. For file sources, this is roughly the same as reading the file into a syntax object using with-module-reading-parameterization and expanding that syntax object using expand. However, string sources and modified sources behave slightly differently, especially with regard to source location information on derived syntax objects:

  • A string source behaves as if it were an anonymous file with no well-defined location on the filesystem. Relative file path imports will not work correctly. Source location information will still be present with line and column numbers, but will claim to be located in a source named 'string instead of a file.

  • A modified source behaves the same as its wrapped unmodified source, except as if its contents were completely replaced. Source location information will be present, but will not correspond to positions within the original source as they will instead refer to positions in the modified contents. If the original source was a file source, accidentally using source locations from the modified source to make edits to the original file will produce malformed changes.

Note that while a file source is being read and expanded, the current directory is parameterized to the file source’s parent directory. This ensures that relative file path imports in source files can still be resolved regardless of what the current directory is before the source is read or expanded. This applies to both modified and unmodified file sources.

procedure

(source-read-language code)  (or/c module-path? #false)

  code : source?
Detects the #lang language of code and returns the module path of that language. Returns #false if code does not begin with a #lang line.

procedure

(source-read-syntax code)  syntax?

  code : source?
Reads code as a syntax object, using the module reading parameterization to allow the source’s #lang to control the reader. Every syntax object within the result is labeled with its original syntax path using the 'original-syntax-path syntax property, as described in Original Syntax Paths and Formatting Preservation.

procedure

(source-expand code)  syntax?

  code : source?
Reads code and fully expands it, as in expand. Because the program is read with source-read-syntax, its subforms are labeled with 'original-syntax-path properties before expansion occurs.

procedure

(source-can-expand? code)  boolean?

  code : source?
Attempts to fully expand code, then returns #true if expansion finished without raising an error and returns #false otherwise.

procedure

(source-text-of code stx)  immutable-string?

  code : source?
  stx : syntax?
Returns the source text within code that produced stx, based on the source location information attached to stx. Raises a contract violation if stx does not have source location information.

procedure

(source-comment-locations code)  immutable-range-set?

  code : source?
Returns a range set containing the positions of all comments in code. This is implemented by looking up the lexer of the #lang that code is written in, using the syntax-color/module-lexer API. Warning: the positions are zero-based, unlike the one-based positions returned from syntax-position. Additionally, positions are in terms of characters and not bytes.