Glossary#
- abstract syntax tree#
- ast#
An intermediate tree data structure used by most compilers after parsing a programming language. The AST stage of Lissp is Hissp, and Lissp is a pretty direct representation of it.
- anaphor#
- anaphoric macro#
An anaphoric macro creates one or more lexical (local) variable bindings without explicitly naming them. Such a bound name is called an anaphor.
- atom#
A
form
that is either the empty tuple()
or not of typetuple
. Atoms are the leaf elements of Hisspâs syntax trees, while non-empty tuples are the nodes.is_node
tests for the non-leaves, so its negation tests for atoms.- bare token#
An
object token
without the initial character marking it as acomment token
(;
),Unicode token
("
),fragment token
(|
), orcontrol token
(:
). It is either aliteral token
, or failing that, asymbol token
.- comment token#
An
object token
consisting of one or more lines, possibly indented with spaces, each starting with a semicolon (;
) character. Comment tokens read ashissp.reader.Comment
instances, a type that is normally discarded by the reader. However, they can still be arguments for atagging token
.- control token#
An
object token
that begins with a colon:
character. It reads as acontrol word
, a type ofstr atom
.- control word#
A
str atom
that begins with a colon:
character. These normally compile directly to Python string literals with the same contents (including the leading colon), but may have special interpretation in some contexts. (Both Python and other Lisps use the term âkeyword
â, but they meandifferent things
, including Lispâs equivalent concept.)is_control
tests for control words.- discard tag#
- discarded item#
_#
. Aspecial tag
used to structurally disable parts of code during development, for commentary, or as adoorstop
. The argument to a discard tag is the discarded item. It is unique amongtagging token
s in that it doesnât return aparsed object
at all. Although atag
could achieve a similar effect by returning a (normally discarded)hissp.reader.Comment
instance or by consuming twoparsed object
s and returning the second one unchanged, the discard tag (like allspecial tag
s) is unary, making it applicable to the last (or only) element in a tuple (such as adoorstop
), and a discarded item cannot be an argument to another tagging token, unlike aComment
instance, which allows its use for commentary between atagging token
and one of its arguments.- doorstop#
A
discarded item
used to âhold openâ a bracket trail or avoid a))
in line. Any discarded item used this way is functionally a doorstop, but, in Lissp, the typical style starts with_#/
and may continue with a label of what form the next)
is closing, like_#/foo
, similar to XML tags.- eof#
End-of-file. In most Unix terminals, use a Ctrl+D, or Ctrl+Z Enter in Windows. Quits a subREPL without also terminating the Python session, unlike
(exit)
, and works similarly in most shells.- form#
An object meant for evaluation; a Hissp expression for passing to the Hissp compiler.
- fragment#
A
fragment token
,fragment atom
, orpython fragment
, depending on context.- fragment atom#
A
str atom
that is not acontrol word
, especially if it does not simply contain an identifier or literal. So called because the compilerâs usual interpretation is to emit the contents directly (making the contents aPython fragment
), although there is a preprocessing step for imports (seemodule handle
).- fragment token#
An
object token
that begins and ends with a vertical line (|
) character. Internal vertical lines must be escaped as two vertical lines (||
). It reads directly as astr atom
, which typically becomes afragment atom
, hence the name. In the case that the fragment token begins with|:
, it becomes acontrol word
instead.- full qualifier#
- full qualification#
- fully-qualified identifier#
A
module handle
prepended to aqualified name
and separated with a.
is a fully-qualified identifier; itâs the path of attribute access from the full import path of the module, which is enough to get a reference to the object from anywhere. Compiles to attribute access from an__import__
expression. E.g.,foo.bar.baz..spam.eggs.bacon
, or, with fewer segments,foo..spam
. The full qualifier part is everything but the last segment, commonly used as an argument toalias
. Full qualification is the process of adding a full qualifier or the state of having a full qualifier.- gensym#
- gensym hash#
A generated
symbol
. These are produced by thegensym tag
. A gensym hash is unique to the template it was created in. This prevents accidental name collisions inmacro expansion
s. A gensym hash is mostly used for local variables because they canât be disambiguated with afull qualifier
.- gensym tag#
$#
. Aspecial tag
only valid in atemplate
for creating agensym
. Prepends agensym hash
to its argument, or replaces$
characters with it.- hissp#
The project at https://github.com/gilch/hissp. The package produced by the project. The language of Python data structures used by the project, which
hissp.compiler
can transpile into executable Python code. The Python data structures encoding this language: aform
, or a series of them. This is also theAST
stage ofLissp
, a programming language implemented in terms of Hissp.- hissp injection#
Any
atom
ofnonstandard
type (or the use thereof), i.e., anything the compiler doesnât have a literal notation for, which it would have to attempt to emit as apickle expression
. This includes instances of standard types without a literal notation (e.g.,float
is a standard type, butmath.nan
has no literal) or collections containing nonstandard elements or cycles. Amacro expansion
may be an injection. Besides macro expansions, in readerless mode, this almost always requires the use of non-literal notation, (i.e., notation not accepted byast.literal_eval
). In Lissp, this almost always requires the use of atagging token
. (A notable exception is a float literal big enough in magnitude to overflow toinf
or-inf
, e.g.,1e999
. The compiler still considers this nonstandard because thatâs not itsrepr
, and would emit apickle expression
for it.) Basic container types containing only standard elements do not count as injections, because the compiler has a notation for them, even though Lissp doesnât.- hissp string#
A
form
orparsed object
which would directly represents a string in Hissp, if evaluated on its own. Allstring literal fragment
s are Hissp strings. Aquote
dstr atom
is also a Hissp string.is_hissp_string
tests for Hissp strings.- inject#
- inject tag#
.#
. Aspecial tag
which evaluates the nextparsed object
and returns its result. So named because itâs typically used to make aninjection
, although it can result in an object of any type.- injection#
Either a
Python injection
or aHissp injection
, depending on context.- invocation#
- invoke#
- invoking#
A tuple
form
that looks like a function call is an invocation. May actually compile to a run-time function call, or may instead be aspecial form
ormacro form
, which calls amacro
at compile time. Or the process of making such a call.- kwarg token#
A single-argument
tagging token
ending in an equals sign (=
) and read as ahissp.reader.Kwarg
instance. Used as keyword arguments for atag
.- literal token#
A
bare token
that is a valid Python literal, as determined byast.literal_eval
, but not of a container type. It reads as anatom
of that type.- macro#
A
macro function
ormacro form
, depending on context.- macro expansion#
- expansion#
- macro form#
A
form
which represents some otherform
, called itsexpansion
. Compilationinvoke
s amacro
to make the substitution.- macro function#
A
metaprogram
meant to run at compile time. A callable attribute of a_macro_
namespace.- metaprogram#
- metaprogramming#
A metaprogram is a program that writes code. Typically, this means the callable referred to by
tag
ormacro
syntax, or helper functions used for abbreviations inreaderless mode
. But the compiler itself is also a kind of metaprogram. Metaprogramming is the process of writing metaprograms.- module handle#
A
str atom
containing a.
-separated path ending in a.
, representing an import path for a module. Any segments before the module name are package names. E.g.,foo.bar.baz.
orfoo.
. The compiler processes it into a__import__
expression before emission.- munging#
The process of replacing characters invalid in a Python identifier with
Quotez
equivalents. Primarily used to make asymbol token
into astr atom
containing a valid Python identifier (asymbol
). The munging machinery is inhissp.munger
.- object token#
A type of
token
which by itself results in aparsed object
when passed to the Lissp parser. These are what the reader considers nouns. Typically emitted as anatom
, but may instead be arguments to atagging token
.- params#
- params tuple#
- params symbol#
The first argument to the
lambda
special form
. It represents the lambda parameters. Typically either a tuple or astr atom
, but other iterables can work. Also amacro
argument that becomes the whole params argument in a lambda expansion, such as the first argument tolet-from
orany*map
. The equivalent concept is called the âlambda listâ in Common Lisp, and the âparams vectorâ in Clojure, but Hissp is made of tuples, not linked-lists or vectors, hence âparams tupleâ when written with a tuple.- parsed object#
The result of parsing an
object token
; or atagging token
with its arguments (except thediscard tag
); or a balanced pair of parentheses (open(
and close)
tokens), with their contents (if any). Typically emitted as aform
, but may instead be arguments to atagging token
.- pickle expression#
The compilerâs final fallback emission when it doesnât have a literal notation for an
atom
. Itâs an import ofpickle.loads
passed abytes
literal containing a serialization of the object. Evaluating it should result in an equivalent object.- python fragment#
A piece of Python code, especially one emitted by the compiler. Typically a Python expression, but not necessarily anything complete. The compiler assembles and emits fragments to produce compiled output.
- python injection#
The technique of writing a
Python fragment
rather than allowing the Hissp machinery to do it for you, or the fragments so used or thefragment atom
containing one. Atext macro
works via Python injection. Injection is discouraged because it bypasses a lot of Hisspâs machinery, and is opaque to code-walking macros, making them less useful or risking errors. However, the compiler only targets a subset of Python expressions. Injection transcends that limitation. Injection of identifiers is consideredstandard
in Hissp, so is not discourarged. A LisspUnicode token
reads as astring literal fragment
, rather than as aquote
dstr atom
, making them an example of injection as well. This usage isstandard
in Lissp.- qualifier#
- qualification#
- partial qualification#
- partially qualified identifier#
A
str atom
containing a.
-separated identifier path prepended to an identifier is a qualified identifier. Compiles to Python attribute access syntax. If this is the path from the containing module, the result is aqualified name
. If this includes amodule handle
, itâsfull qualification
, if qualification is not full, itâs partial. Aqualified name
is partial qualification, but partial qualification is not necessarily aqualified name
, because the path may start from some namespace other than the module globals. The qualifier part is everything but the last segment. Qualification is the process of adding a qualifier or the state of having a qualifier.hissp.macros._macro_.alias
produces atag
to abbreviate a qualifier.- quote#
- hard quote#
'
. Aspecial tag
abbreviating thequote
special form
. Sometimes called a âhard quoteâ to distinguish it from thetemplate quote
.- quotez#
The
munger
âs character replacement format. Itâs the characterâs Unicode name wrapped inQz
and_
. (Spaces becomex
and hyphens becomeh
.) Characters without names use their hexadecimal ordinals instead. Some ASCII characters use the short names fromTO_NAME
instead. Thegensym
hashes andhissp.compiler.MAYBE
use the sameQz{}_
wrapper.- read time#
The phase before compilation proper that translates Lissp to Hissp: when the
reader
runs and whentagging token
s are activated.- readerless mode#
A representation of
form
s in the Python language using mostly literals. Hissp written this way does not require the use of a reader, hence itâs the âreaderlessâ mode of writing Hissp.- repl#
- read-evaluate-print loop#
- read-eval-print loop#
The
LisspREPL
, Lisspâs interactive interpreter shell, layered on Pythonâs. (Or a similar language shell.) Reads Lissp input, compiles it to Python, and passes it to Pythonâs shell for evaluation and printing, then repeats. Used for inspection, online help, interactive development, and debugging. A subREPL is just a REPL started from within a REPL, analogous to a subshell.- special form#
A
form
special-casedin the compiler
. These are tuples beginning with either aquote
orlambda
str atom
. They look like function calls but act more like macros, in that arguments are not all evaluated first. While acontrol word
is aform
and can have special interpretations in certain contexts, they are not considered special forms.module handle
s also have a processing rule in the compiler, but arenât considered special forms.- special tag#
One of the built-in unary
tagging token
s treated as aspecial case
in thereader
.- splice#
- splicing unquote#
,@
. Aspecial tag
only valid in atemplate
. Its argument is interpolated and unpacked rather than quoted first.- standalone property#
When the compiled Python output of Hissp doesnât depend on the
hissp
package, it can run in a Python environment that doesnât havehissp
installed. Hissp was designed for this, but it can be lost by adding ahissp
import explicitly. Using Hisspâsmetaprogramming
helpers only in metaprograms (or in metaprogramming helper functions only called by metaprograms) is fine because metaprograms only run at compile time (orread time
), so they wonât crash at run time even whenhissp
cannot be imported. Forgetting to remove or disable import oftranspile
used in main or a package__init__
is another way the standalone property can be lost.- standard#
- nonstandard#
The standard language is a disciplined subset with full generality. Standard (
readerless mode
) Hissp usesstr atom
s only forcontrol word
s andsymbol
s (which include imports and attribute access) and avoids otherPython injection
s. Standard Lissp also usesstr atom
s forstring literal fragment
s. (Standard readerless mode instead compiles string literals exclusively via the quotespecial form
, or nested inset
,dict
, orlist
atom
s.) Other Python injections are considered nonstandard. Nonstandard constructions should be used sparingly and with care. Metaprograms are not necessarily expected to handle nonstandard Python injections, because that would require processing the much more complicated language of Python expressions, but not all nonstandard injections are problematic. The bundled tags and macros mostly avoid nonstandard injections in expansions, but (with the notable exception ofmix
) allow them where they would be no worse than an opaquefully-qualified identifier
, or in a few cases where the user writes part of the injection. Standard Hissp also avoids importing thehissp
package outside of metaprograms (and direct helpers not otherwise called) to preserve thestandalone property
. Standard atom types are those the compiler has a literal notation for. Use of nonstandard types can result in apickle expression
or a crash during compilation (if the atom is unpickleable).- stararg token#
One of
*=
or**=
. Aspecial tag
which reads as ahissp.reader.Kwarg
instance. Used as unpacking positional or keyword arguments (respectively) to atag
.- str atom#
An
atom
of typestr
. Usually represents aPython fragment
. If it starts with a colon (:
), it is acontrol word
. May contain amodule handle
.- string literal fragment#
A
Python fragment
whichast.literal_eval
would evaluate to an object of typestr
. Not allstr atom
s are string literal fragments; it must contain a Python string literal expression.is_string_literal
tests for string literal fragments.- subform#
A
form
nested inside a tuple form; a Hissp subexpression. An (e.g.)params tuple
isnât aform
, so itâs not a subform either, but a default argument inside it would be. Similarly, macro arguments donât necessarily count as subforms.- symbol#
A
module handle
or aPython fragment
containing anidentifier
. (Possibly withqualification
.) A symbol is always astr atom
.is_symbol
tests for symbols. Some identifiers arereserved
in Python and canât be used as variable/attribute names (Boolean operations
,None
,class
, etc.) These still count as symbols.- symbol token#
A
bare token
that is not aliteral token
. These are subject tomunging
and read as asymbol
, a type ofstr atom
used for identifiers.- tag#
- tag token#
- hash tag#
- module-local tag#
- fully-qualified tag#
A
tagging token
that ends in one or more number sign (#
) characters (also known as âhashâ characters, making these âhash tagsâ when distinguishing them from othertagging token
s.) If it includes amodule handle
part, itâs a fully-qualified tag. Any callable accessible this way can be applied as a tag. E.g.builtins..str.format##
,fractions..Fraction#
,textwrap..dedent#
, etc. If it doesnât, it refers to a module-localmetaprogram
stored in the moduleâs_macro_
namespace. These usually need to be pure or at least idempotent, as theREPL
or similar tooling may have to make multiple attempts at applying them.- tagging token#
A type of
token
that, when read, consumes one or moreparsed object
s and results in aparsed object
. These can be thought of as reader adjectives. They serve a function similar to reader macros in other Lisps, but operate on theparsed object
stream (parser level), not the raw character stream (lexer level). Think Clojure/EDN tags, not Common Lisp reader macros.- template#
A
template quote
and its argument, a domain-specific language (DSL) for creating aform
, supporting tuple interpolation,gensym
s, and automaticfull qualification
. Can also be used for data, not just code. Typically used in the definition of amacro function
.- template quote#
- soft quote#
`
. Aspecial tag
starting atemplate
. The equivalent concept is called a âquasiquoteâ or âsyntax quoteâ in other Lisps.- text macro#
A
macro
thatexpands
to astr atom
instead of some otherform
, especially if thestr atom
doesnât simply contain a string literal or (possibly qualified) identifier. Effectively, they return Python code, rather than Hissp, which makes them opaque to Hisspmetaprogramming
, like pre-expanding, code-walking macros.- token#
A lexical unit of Lissp. This is how the
reader
chunks Lissp in preparation for parsing. Some are considered implementation details, but a Lissp programmer should be able to mentally parse the language.- top level#
- top-level form#
A form not nested inside another form, or the location of such a form. âTopâ here means the top of the syntax tree rather than the top of the file. Each top-level form is a compilation unit. A macro defined in a top-level form cannot affect any other
subform
in the same top-level form, because by the time it exists, the top-level form has already been compiled.Injection
of a Python statement is only valid at the top level.- unicode token#
An
object token
that begins and ends with a quotation mark ("
) character. They may contain newline characters like Pythonâs triple-quoted string literals, as is typical of Lisps. Internal quotation marks must be escaped with a preceding reverse solidus (\
) character. It reads as astring literal fragment
, specifically, astr atom
containing a Python string literal wrapped in parentheses.- unqualified#
An identifier without a
qualifier
. An unqualifiedtag
is only valid if itâs available as an attribute in the current moduleâs_macro_
namespace, and similarly for an unqualifiedmacro
. A unqualified variable is valid if itâs in thebuiltins
module, a global of the current module, or a variable in the current lexical scope.- unquote#
,
. Aspecial tag
only valid in atemplate
. Its argument is directly interpolated rather than quoted first.