Introduction
Understanding the book, the grammar, and the runtime model.
hara.lang is best understood as a language-oriented templating system built for real multi-language applications. It stores code in a reusable intermediate form, emits that form through a target grammar, and can then hand the result to a matching runtime.
1 The core idea
Instead of writing and maintaining every target language by hand, hara.lang lets you author code in a Lisp DSL and describe each target language as a grammar. That grammar controls how forms are emitted, which macros expand, which operators exist, and what dependencies or native fragments are required.
A language is a structured library
A Book stores the target language identity, grammar, parent relationship, modules, and code entries. That means emitted code is traceable back to named modules and functions instead of being anonymous text.
Syntax is data
Reserved operators, blocks, data literals, top-level forms, and special emit hooks are declared in the grammar, which makes a new target language mostly a matter of defining conventions.
Namespaces become language modules
Using l/script installs a module into the current language book, imports relevant macros, and connects the namespace to a runtime configuration for further evaluation.
1.1 Walkthrough
The fastest way to see the book and grammar model is to emit the same small function to two targets. l/emit-as takes a language keyword and a quoted hara.lang form, and returns the emitted string.
emit a function to JavaScript
^{:refer hara.lang/emit-as :added "4.0"}
(l/emit-as :js '[(defn add [a b]
(return (+ a b)))
(add 1 2)])
=> "function add(a,b){\n return a + b;\n}\n\nadd(1,2)"
emit the same function to Lua
^{:refer hara.lang/emit-as :added "4.0"}
(l/emit-as :lua '[(defn add [a b]
(return (+ a b)))
(add 1 2)])
=> "local function add(a,b)\n return a + b\nend\n\nadd(1,2)"
l/script- installs a script context into the current namespace. Once installed, !.js evaluates expressions in place, and defn.js stores functions as book entries that can be called like Clojure functions.
install a script context and call a generated function
^{:refer hara.lang/script- :added "4.0"}
(do
(l/script- :js
{:require [[xt.lang.spec-base :as xt]]})
(defn.js add [a b]
(return (+ a b)))
(add 1 2))
=> "add(1,2)"
2 Why not just transpile?
Straight transpilation is usually about converting one source language into one target language. hara.lang aims at a broader problem: shared authoring and maintenance across many targets and runtimes.
3 Where it fits well
Shared logic across JS, Lua, Python, and more
A single conceptual model can be emitted to different environments when those environments share enough structure.
Tight feedback loops
Because authoring, testing, and maintenance stay in Clojure, teams can iterate on generated code without jumping across unrelated toolchains for every edit.
New targets are incremental
Adding a target language does not require rebuilding the world. A grammar, a runtime adapter, and a set of useful library modules are often enough to make it productive.
The mental model
shared forms -> preprocess + stage -> grammar-driven emission -> target code -> runtime adapter
4 hara.lang.base.book and hara.lang.base.library Summary
The std.lang.base.book* and std.lang.base.library* namespaces define the data structures for storing, managing, and accessing code within the foundation-base ecosystem. A "library" is a collection of "books," each of which represents a language and contains the code and grammar for that language.
Core Concepts:
- Library (
hara.lang.base.library): ALibraryis the top-level container for all language definitions. It holds a "snapshot" of the current state of all books.n Snapshot (hara.lang.base.library-snapshot): ASnapshotis an immutable map of language IDs to book definitions. It represents a specific version of the library's content.n Book (hara.lang.base.book): ABookholds all the code for a particular language. It contains a map of modules, a grammar, and metadata about the language.n Module (std.lang.base.book-module): AModulerepresents a single source file or a collection of related code. It contains a map of code entries, as well as information about the module's dependencies, exports, and other properties.n Entry (hara.lang.base.book-entry): AnEntryrepresents a single piece of code, such as a function, a variable, or a macro. It contains the code itself (as a Clojure form), as well as metadata about the code.
How Forms are Stored as Code:
The BookEntry record is the key to understanding how forms are stored as code. Here's a breakdown of its most important fields:
:form: This field holds the actual Clojure form that represents the code. This is the raw, unevaluated code that will be processed by the emit pipeline.n:form-input: This field holds the "input form," which is the result of the first stage of preprocessing (to-input).n:deps: This field holds a set of symbols that represent the dependencies of the code. These dependencies are resolved during theto-stagingphase of preprocessing.n:namespace: This field holds the namespace of the code.n:templateand:standalone: These fields are used for macros and templates.
The Library and Book Data Structures:
Library: A record with an:instancefield that holds an atom containing the currentSnapshot.nSnapshot: An immutable map where keys are language keywords (e.g.,:lua,:js) and values are maps containing a:bookkey.nBook: A record with the following fields:n:lang: The language of the book.n:meta: ABookMetarecord with language-specific metadata.n:grammar: The grammar for the language.n:modules: A map ofBookModulerecords.nBookModule: A record with fields for:code,:fragment(macros),:alias,:link,:export, etc.nBookEntry: A record with fields for:form,:deps,:namespace, etc.
Interaction with the Emit Pipeline:
The library and book are essential for the emit pipeline.
- The
emitfunction takes alibrary(or asnapshot) as an argument, which it uses to get thebookfor the target language.n Thebookprovides thegrammarthat is used to emit the code.n Themodulesin thebookare used to resolve dependencies and to find the code for other functions and macros that are used in the form being emitted.
Example: Creating and Using a Library
hara.lang.base.book and hara.lang.base.library Summary example
(require '[hara.lang.base.library :as lib])
(require '[hara.lang.base.book :as book])
(require '[hara.lang.base.book-module :as module])
(require '[hara.lang.base.book-entry :as entry])
;; 1. Define a code entry
(def my-entry
(entry/book-entry
{:lang :my-lang, :id 'my-fn, :module 'my-module, :section :code,
:form '(defn my-fn [x] (+ x 1))}))
;; 2. Define a module
(def my-module
(module/book-module
{:lang :my-lang, :id 'my-module, :code {'my-fn my-entry}}))
;; 3. Define a book
(def my-book
(book/book
{:lang :my-lang, :grammar my-grammar, :modules {'my-module my-module}}))
;; 4. Create a library and add the book
(def my-library (lib/library {}))
(lib/add-book! my-library my-book)
;; 5. Emit code using the library
(impl/emit-str '(my-module/my-fn 1) {:lang :my-lang :library my-library})
This example shows how to create a library, add a book to it, and then use the library to emit code. The library provides the necessary context (grammar and modules) for the emit pipeline to do its work.
By providing a structured way to store and manage code, the hara.lang.base.book* and hara.lang.base.library* namespaces play a crucial role in the foundation-base transpiler.
5 hara.lang.base.emit Summary
The std.lang.base.emit* namespaces form the core of the foundation-base code generation and transpilation engine. Their primary responsibility is to take a Clojure-like data structure, referred to as a "form," and translate it into a string of code in a target language. This entire process is orchestrated by a grammar that specifies the syntax, semantics, and customization points for the target language.
Core Concepts:
- Emit Pipeline: The process of code generation is a multi-stage pipeline that transforms the input form into the final output string. The main entry point is
std.lang.base.emit/emit, which takes a form, a grammar, a namespace, and a map of options.n Grammar: Thegrammaris a rich data structure (a Clojure map) that defines how to emit different forms. It contains detailed information about reserved words, operators, data structures, control flow, function definitions, and more. The grammar is the primary mechanism for customizing the output for different target languages.n Dispatch: The emit process uses a multi-dispatch mechanism to determine how to emit a given form. Thestd.lang.base.emit-common/form-keyfunction analyzes a form and returns a key that is used to look up the appropriate emit function in the grammar's:reservedmap.n* Customization: The emit pipeline is designed to be highly customizable. Developers can override default emit functions, define new language constructs through macros, and control the formatting and layout of the generated code.
The Emit Pipeline in Detail:
- Preprocessing (
hara.lang.base.emit-preprocess):nto-input: This is the first step, where the raw Clojure form is converted into an "input form." This involves expanding special reader macros and other syntactic sugar into a more canonical representation. For example,@is expanded to a!:derefform.nto-staging: This is the second and more complex preprocessing step. It takes the input form and prepares it for emission by:n Resolving symbols and namespaces.n Expanding macros defined in the grammar.n Handling dependencies between different code modules.n Processing inline function assignments.nn2. Emission (hara.lang.base.emit):nemit-main: The main entry point for the emission process. It sets up the dynamic environment and callsemit-main-loop.nemit-main-loop: This is the core recursive function that traverses the preprocessed form. For each node in the form, it callsemit-form.nemit-form: This function is the central dispatcher. It callsform-keyto determine the type of the current form and then dispatches to the appropriate emit function (e.g.,emit-def,emit-fn,emit-block).nn3. Form-Specific Emitters:n Thehara.lang.base.emit-*namespaces provide the actual implementation for emitting different types of forms.nemit-top-level: Handles top-level forms likedef,defn, anddefclass.nemit-fn: Handles function definitions and calls, including argument lists and type hints.nemit-block: Handles block-level constructs likedo,if,for, andwhile.nemit-data: Handles the emission of data literals like maps, vectors, lists, and sets.nemit-assign: Handles assignment operations.nemit-special: Handles special forms like!:eval(for evaluating code at compile time) and!:lang(for embedding code from another language).
Customizing the Pipeline:
The emit pipeline is designed for extensive customization, primarily through the grammar map.
- The Grammar:n The grammar is a nested map that contains all the information needed to emit code for a specific language.n The
:defaultkey in the grammar contains default settings for things like comments, common syntax elements (e.g., statement terminators, namespace separators), and function/block structure.n The:tokenkey allows customization of how different token types (e.g., strings, symbols, keywords) are emitted.n The:datakey controls the emission of data structures.n The:definekey controls the emission of top-level definitions.n The:blockkey controls the emission of block-level constructs.nn Reserved Words and Operators:n The:reservedmap in the grammar is used to define how specific symbols are treated. For each symbol, you can specify:n:emit: The type of emission to use (e.g.,:infix,:prefix,:macro).n:raw: The raw string to emit for the symbol.n:macro: A macro function to be expanded during preprocessing.n:block: A map defining the structure of a block-level construct.nn Macros:n Macros provide a powerful way to extend the language. A macro is a function that is called during preprocessing and returns a new form to be emitted.n Macros are defined in the:reservedmap with an:emitvalue of:macroand a:macrokey pointing to the macro function.nn Custom Emit Functions:n You can provide a custom emit function for any form by adding an:emitkey to its definition in the:reservedmap. The value of the:emitkey should be a function that takes the form, grammar, and options map as arguments and returns the emitted string.nn Dynamic Variables:n Several dynamic variables can be used to control the output:n*indent*: The current indentation level.n*compressed*: If true, emits the code in a compressed format without newlines or extra spaces.n*trace*: If true, prints the form being emitted at each step of the recursion.n **explode*: If true, prints a stack trace on error.
Example: Customizing an Operator
To customize the + operator to emit add instead, you would modify the grammar like this:
hara.lang.base.emit Summary example
(def +my-grammar+
(h/merge-nested
helper/+default+
{:reserved {\+ {:emit :infix :raw "add"}}}))
(emit/emit '(+ 1 2) +my-grammar+ 'my.ns {})
=> "1 add 2"
This detailed control over the emission process makes the foundation-base transpiler a flexible and powerful tool for code generation.
6 hara.lang.base.grammar Summary
The std.lang.base.grammar* namespaces are responsible for defining the structure and semantics of a language that can be emitted by the foundation-base transpiler. The grammar is a key component of the emit pipeline, providing the necessary information to translate a Clojure-like form into a string of code in the target language.
Core Concepts:
- Grammar: A grammar is a Clojure map that defines the syntax and semantics of a target language. It is created using the
std.lang.base.grammar/grammarfunction, which takes a tag, a map of reserved words, and a template as arguments.n Reserved Words: The:reservedmap in the grammar defines how specific symbols are treated by the emitter. For each symbol, you can specify itsop(operation),emittype (e.g.,:infix,:prefix,:macro),rawstring representation, and other properties.n Operators (+op-*): Thestd.lang.base.grammar-spec,std.lang.base.grammar-macro, andstd.lang.base.grammar-xtalknamespaces define a large set of operators that can be used to build a grammar. These operators cover a wide range of functionalities, from basic arithmetic and logic to more advanced features like macros and cross-language interoperability (xtalk).n* Building a Grammar: Thestd.lang.base.grammar/buildfunction is used to construct a grammar by selecting a set of operators from the available+op-*definitions. You can include or exclude specific operator groups to create a grammar that is tailored to your needs.
How the Grammar Fits into the Emit Pipeline:
The grammar is a central component of the emit pipeline, and it is used at every stage of the process:
- Preprocessing:n During the
to-stagingphase, the grammar's:reservedmap is used to identify and expand macros.n The grammar is also used to resolve symbols and namespaces.nn2. Emission:n Theemit-main-loopuses theform-keyfunction to determine the key for a form, which is then used to look up the corresponding entry in the grammar's:reservedmap.n Theemit-formfunction uses the information in the grammar to dispatch to the appropriate emit function (e.g.,emit-def,emit-fn,emit-block).n * The form-specific emit functions use the grammar to get information about syntax, formatting, and other language-specific details. For example,emit-infixuses the:rawvalue from the grammar to get the string representation of the operator.
Customization:
The grammar provides a powerful mechanism for customizing the emit pipeline:
- Defining a New Language: You can define a new language by creating a new grammar that specifies the syntax and semantics of the language.n Extending an Existing Language: You can extend an existing language by adding new operators and macros to its grammar.n Overriding Default Behavior: You can override the default behavior of the emitter by providing your own emit functions in the grammar.n* Controlling Formatting: The grammar allows you to control the formatting and layout of the generated code by specifying options for indentation, spacing, and newlines.
Language-Specific Grammars in hara.lang.model:
The hara.lang.model.* files provide concrete examples of how to define grammars for different languages. These files demonstrate how to:
- Select a set of features: Each language-specific grammar starts by selecting a set of features (operators) from the
+op-*definitions usinggrammar/build. For example,spec_c.cljexcludes:data-shortcuts,:control-try-catch, and:class, which are not relevant for the C language.n Override and extend features: The grammars then usegrammar/build:overrideandgrammar/build:extendto customize the selected features. For example,spec_lua.cljoverrides the:seteqoperator to emit<-instead of=, and it extends the grammar with Lua-specific operators like:cat(for string concatenation) and:len(for getting the length of a table).n Define a template: Each grammar defines a+template+map that specifies the language-specific syntax and formatting rules. This includes things like comment prefixes, statement terminators, namespace separators, and how to emit data structures like maps and vectors.n* Create a book: Finally, each grammar is packaged into abookusingbook/book. The book contains the grammar, as well as metadata about the language, such as how to handle module imports and exports.
Example: The Lua Grammar (spec_lua.clj)
The Lua grammar provides a good example of how to customize the emit pipeline for a specific language. Here are some key features of the Lua grammar:
- Custom
varmacro: Thetf-localmacro provides a more flexible way to declare local variables in Lua.n Customforloop macros: Thetf-for-object,tf-for-array,tf-for-iter, andtf-for-indexmacros provide different ways to iterate over data structures in Lua.n Custom map key emission: Thelua-map-keyfunction provides custom logic for emitting map keys, taking into account Lua's syntax for table keys.n* C FFI support: Thetf-c-ffimacro allows you to embed C code in your Lua code.
By studying the language-specific grammars in hara.lang.model, you can get a good understanding of how to create your own grammars and customize the emit pipeline to support new languages or extend existing ones.
7 hara.lang.base.runtime Summary
The std.lang.base.runtime* and std.lang.base.impl* namespaces, along with rt.basic, are responsible for defining, managing, and interacting with language runtimes in the foundation-base ecosystem. A runtime is an environment where code can be executed. The system is designed to be extensible, allowing new runtimes to be defined and integrated.
Core Concepts:
- Runtime: A runtime is a component that provides an execution environment for a specific language. It implements the
std.protocol.context/IContextandstd.protocol.component/IComponentprotocols, which define the interface for interacting with the runtime.ndefimpl: Thedefimplmacro fromstd.lib.implis the primary tool for creating new runtime types. It simplifies the process of defining adefrecordthat implements one or more protocols.n Runtime Proxy: A runtime proxy (hara.lang.base.runtime-proxy) is a runtime that forwards calls to another runtime. This is useful for creating aliases or for providing a different interface to an existing runtime.n Book: Abook(hara.lang.base.book) is a data structure that contains all the code and metadata for a specific language. Each runtime is associated with a book.n Pointer: Apointer(hara.lang.base.pointer) is a reference to a piece of code in a book. Runtimes use pointers to execute code.n* Lifecycle: Runtimes have a lifecycle that is managed by thestd.protocol.component/IComponentprotocol. This includesstart,stop, andkillfunctions.
Runtime Generation and Customization:
The foundation-base ecosystem provides a flexible way to define and customize runtimes.
1. Defining a Runtime with defimpl:
A new runtime is typically defined using the defimpl macro. This macro takes a name, a list of fields, and a set of protocol implementations.
hara.lang.base.runtime Summary example
(defimpl MyRuntime [field1 field2]
:protocols [std.protocol.context/IContext
:body {-raw-eval (fn [this string]
;; implementation for evaluating a raw string
)}
std.protocol.component/IComponent
:body {-start (fn [this]
;; implementation for starting the runtime
this)
-stop (fn [this]
;; implementation for stopping the runtime
this)}])
IContextProtocol: This protocol defines the core interface for interacting with a runtime. Key functions include:n-raw-eval: Evaluates a raw string of code in the runtime's context.n-invoke-ptr: Invokes a function pointer with specified arguments.n-deref-ptr: Dereferences a pointer to get its value.n-init-ptr: Initializes a pointer in the runtime.nnIComponentProtocol: This protocol defines the component lifecycle for the runtime. Key functions include:n-start: Starts the runtime, preparing it for execution.n *-stop: Stops the runtime, releasing any resources.
2. The RuntimeDefault Record:
The hara.lang.base.runtime namespace defines a RuntimeDefault record using defimpl. This record provides a default implementation for the IContext and IComponent protocols.
- It serves as a base for many of the language-specific runtimes in
rt.basic.n It includes logic for proxying calls to another runtime via theredirectfield.n Thedefault-*functions inhara.lang.base.runtimeprovide the actual implementations for the protocol functions. For example,default-invoke-ptrhandles the logic for invoking a function pointer.
3. Customization:
- Extending
RuntimeDefault: The easiest way to create a new runtime is to extendRuntimeDefaultand override the functions that need to be customized.n Creating a New Runtime from Scratch: For more advanced use cases, you can create a new runtime from scratch by implementing theIContextandIComponentprotocols yourself.n Runtime Proxies: Thehara.lang.base.runtime-proxynamespace allows you to create a proxy for an existing runtime. This is useful for adding functionality or for creating a different interface to a runtime.
Example: A Simple Runtime Definition
The following example from rt.basic.type-basic shows how a basic runtime is defined using defimpl:
hara.lang.base.runtime Summary example
(defimpl RuntimeBasic [id lang]
:protocols [protocol.context/IContext
:body {-raw-eval eval-string}
protocol.component/IComponent
:body {-start start-basic
-stop stop-basic}])
This defines a RuntimeBasic record that implements the IContext and IComponent protocols. The -raw-eval function is implemented by eval-string, and the -start and -stop functions are implemented by start-basic and stop-basic, respectively.
By using defimpl and the provided protocols, the foundation-base ecosystem makes it easy to create new runtimes and to extend the functionality of existing ones.
8 hara.lang.base.script Summary
The std.lang.base.script* namespaces provide a high-level interface for interacting with the foundation-base language ecosystem. They tie together the grammar, emit, book, and runtime components to provide a seamless experience for defining, compiling, and executing code in different languages.
Core Concepts:
- Script: A "script" is a self-contained unit of code that can be executed in a specific language runtime.n
scriptmacro: Thescriptmacro is the main entry point for defining a script. It takes a language keyword, a module name, and a configuration map as arguments.n Runtime Management: Thehara.lang.base.script-controlnamespace provides functions for managing the lifecycle of language runtimes, includingscript-rt-get,script-rt-stop, andscript-rt-restart.n* Annex: An "annex" (hara.lang.base.script-annex) is a way to extend an existing language with new functionality. It allows you to define new macros and functions that can be used in the extended language.
How hara.lang.base.script Ties Everything Together:
The script macro is the glue that holds the foundation-base language ecosystem together. When you use the script macro, it performs the following steps:
- Module Definition: It defines a new module in the
bookfor the specified language. This module contains the code and metadata for the script.n2. Runtime Initialization: It gets or creates a runtime for the specified language usingscript-rt-get.n3. Macro and Highlight Interning: It interns the macros and highlight symbols from the language's grammar into the current namespace, making them available for use in the script.n4. Code Execution: The code within thescriptmacro is then executed in the context of the specified language runtime.
The ! Macro:
The ! macro provides a convenient way to switch between different language runtimes within the same namespace. This is especially useful for testing and for writing polyglot scripts.
hara.lang.base.script Summary example
(require '[hara.lang.base.script :as script])
(script/script :lua my-lua-module)
(script/script+ [:py :python] {})
(!:lua (+ 1 2))
=> 3
(!:py (+ 1 2))
=> 3
In this example, the script macro is used to set up the :lua runtime, and the script+ macro is used to set up the :python runtime as an annex. The ! macro is then used to execute code in each of these runtimes.
Summary:
The std.lang.base.script* namespaces provide a powerful and flexible way to work with multiple languages in the foundation-base ecosystem. By abstracting away the details of runtime management and code compilation, they allow developers to focus on writing code in the language of their choice. The script and ! macros, in particular, provide a seamless and intuitive way to work with polyglot code.
9 hara.lang: A Comprehensive Summary (including submodules)
The std.lang module is the core of the foundation-base ecosystem, providing a powerful and extensible framework for defining, transpiling, and managing multiple programming languages. It enables developers to write code in a Clojure-like DSL and then generate equivalent code in various target languages (JavaScript, Lua, Python, C, Rust, GLSL, Bash, Scheme, JQ, PostgreSQL, etc.). This module is central to the project's goal of creating a polyglot development environment with unified tooling and runtime management.
9.1 hara.lang (Main Namespace)
This namespace orchestrates the functionality of its submodules, providing a high-level interface for language definition, code generation, and runtime interaction. It re-exports key functions from its sub-namespaces, making it a convenient entry point for language-oriented programming.
Key Re-exported Functions:
- From
hara.lang.base.util:sym-full,sym-id,sym-module,sym-pair,sym-default-str,ptr.n Fromhara.lang.base.emit-common:with:explode,with-trace.n Fromhara.lang.base.emit:with:emit,emit*.n Fromhara.lang.base.emit-helper:basic-typed-args,emit-type-record.n Fromhara.lang.base.emit-preprocess:macro-form,macro-opts,macro-grammar,with:macro-opts.n Fromhara.lang.base.impl:emit-script,emit-str,emit-as,emit-symbol,default-library,default-library:reset,runtime-library,with:library,grammar.n Fromhara.lang.base.impl-entry:emit-entry,with:cache-none,with:cache-force.n Fromhara.lang.base.impl-deps:emit-entry-deps.n Fromhara.lang.base.pointer:with:print,with:print-all,with:clip,with:input,with:raw,with:rt,with:rt-wrap,rt:macro-opts.n Fromhara.lang.base.script:script,script-,script+,!,annex:get,annex:start,annex:stop,annex:restart-all,annex:start-all,annex:stop-all,annex:list.n Fromhara.lang.base.script-def:tmpl-entry,tmpl-macro.n Fromhara.lang.base.library:get-book-raw,get-book,get-module,get-snapshot,delete-module!,delete-modules!,delete-entry!,purge-book!.n Fromhara.lang.base.script-lint:lint-set,lint-clear.n Fromhara.lang.base.util:rt,rt:list,rt:default.n Fromhara.lang.base.script-control:rt:restart,rt:stop.n Fromstd.lang.base.workspace:sym-entry,module-entries,emit-ptr,emit-module,print-module,ptr-clip,ptr-print,ptr-setup,ptr-teardown,ptr-setup-deps,ptr-teardown-deps,rt:module,rt:module-purge,rt:inner,rt:restart,rt:setup,rt:setup-to,rt:setup-single,rt:scaffold,rt:scaffold-to,rt:scaffold-imports,rt:teardown,rt:teardown-at,rt:teardown-single,rt:teardown-to,intern-macros.n Fromhara.lang.base.manage:lib:overview,lib:module,lib:entries,lib:purge,lib:unused.
Key Functions:
rt:space: Retrieves the runtime for a given language and namespace.nget-entry: Retrieves a book entry from a pointer or map.nas-lua: Transforms Clojure vectors to Lua tables (empty vectors to empty maps).nrt:invoke: Invokes code in a specified runtime.nforce-reload: Forces reloading of a namespace and its dependents.
9.2 hara.lang.base.book (Language Book Management)
This sub-namespace defines the core data structures for storing and managing language definitions, including books, modules, and entries. It provides functions for accessing and manipulating these structures.
Core Concepts:
BookRecord: Represents a language definition, containing itslang,meta(metadata),grammar,modules,parent(for inheritance), andreferencedmodules.nBookModuleRecord: Represents a single source file or a collection of related code within a language, containingalias,link,nativeimports,codeentries,fragment(macros), andstaticmetadata.nBookEntryRecord: Represents a single piece of code (function, macro, variable), containing itsid,module,section(code, fragment, header),form,form-input,deps,namespace, andstaticmetadata.
Key Functions:
get-base-entry,get-code-entry,get-entry,get-module: Functions for retrieving entries and modules from a book.nget-code-deps,get-deps: Functions for retrieving dependencies of code entries and modules.nlist-entries: Lists entries within a book.nbook-string: Returns a string representation of a book.nbook?,book: Predicate and constructor forBookrecords.nbook-merge: Merges a book with its parent book (for language inheritance).nbook-from: Returns a merged book from a snapshot.ncheck-compatible-lang,assert-compatible-lang: Checks and asserts language compatibility.nset-module,put-module,delete-module,delete-modules,has-module?,assert-module: Functions for managing modules within a book.nset-entry,put-entry,delete-entry,has-entry?,assert-entry: Functions for managing entries within a module.nmodule-create-bundled: Creates bundled packages for modules.nmodule-create-filename: Generates a filename for a module.nmodule-create-check: Checks for bundle availability.nmodule-create-requires: Creates a map for module requirements.nmodule-create: Creates aBookModulerecord.n*module-deps: Gets dependencies for a module.
9.3 hara.lang.base.compile (Code Compilation and Output)
This sub-namespace provides functions for compiling and writing generated code to files, supporting various output formats and module structures.
Key Functions:
compile-script: Compiles a single script entry.ncompile-module-single: Compiles a single module.ncompile-module-graph-rel: Extracts the relative path for a module in a graph.ncompile-module-graph-single: Compiles a single module file within a graph.ncompile-module-graph: Compiles a graph of modules.ncompile-module-directory-single: Compiles a single module file within a directory structure.ncompile-module-directory: Compiles modules from a directory structure.n*compile-module-schema: Compiles all modules into a single schema file (e.g., for SQL).
9.4 hara.lang.base.emit (Code Emission Pipeline)
This sub-namespace defines the core code emission pipeline, responsible for transforming Clojure forms into target language strings based on a grammar.
Core Concepts:
default-grammar: Provides a base grammar with common settings.nemit-main-loop: The recursive function that traverses forms and dispatches to appropriate emitters.nemit-main: The main entry point for emitting a single form.nemit: Emits a form to an output string, handling grammar and options.nwith:emit(macro): Binds the top-level emit function.nprep-options: Prepares options for the emit pipeline.nprep-form: Preprocesses a form through different stages (raw, input, staging).
9.5 hara.lang.base.emit-assign (Assignment Emission)
This sub-namespace handles the emission of assignment-related forms, including inline function assignments and variable declarations.
Key Functions:
emit-def-assign-inline: Emits an inline function assignment.nemit-def-assign: Emits a variable declaration or assignment.ntest-assign-loop,test-assign-emit: Test functions for assignment emission.
9.6 hara.lang.base.emit-block (Block Emission)
This sub-namespace handles the emission of control flow blocks (do, if, for, while, try, switch) and their associated parameters and bodies.
Key Functions:
emit-statement: Emits a single statement.nemit-do,emit-do*: Emitsdoblocks.nblock-options: Retrieves options for a block.nemit-block-body: Emits the body of a block.nparse-params: Parses parameters for a block.nemit-params-statement,emit-params: Emits parameters for a block.nemit-block-control,emit-block-controls: Emits control flow constructs within a block.nemit-block-setup: Prepares a block for emission.nemit-block-inner: Emits the inner content of a block.nemit-block-standard: Emits a generic block.nemit-block: The main function for emitting block expressions.n*test-block-loop,test-block-emit: Test functions for block emission.
9.7 hara.lang.base.emit-common (Common Emission Utilities)
This sub-namespace provides fundamental utilities and dynamic variables used across the entire emission pipeline, such as indentation, tracing, and generic emission functions.
Core Concepts:
- Dynamic Variables:
*explode*,*trace*,*indent*,*compressed*,*multiline*,*max-len*,*emit-internal*,*emit-fn*.n* Emission Types::discard,:free,:squash,:comment,:indent,:token,:alias,:unit,:internal,:internal-str,:pre,:post,:prefix,:postfix,:infix,:infix-,:infix*,:infix-if,:bi,:between,:assign,:invoke,:new,:static-invoke,:index,:return,:macro,:template,:with-global,:with-decorate,:with-uuid,:with-rand.
Key Functions:
with:explode,with-trace,with-compressed,with-indent(macros): Control dynamic emission settings.nnewline-indent: Returns a newline with appropriate indentation.nemit-reserved-value: Emits a reserved value.nemit-free-raw,emit-free: Emits free-form text.nemit-comment: Emits a comment.nemit-indent: Emits an indented form.nemit-macro: Emits a macro.nemit-array: Emits an array of forms.nemit-wrappable?: Checks if a form is wrappable.nemit-squash: Emits a squashed representation.nemit-wrapping: Emits a potentially wrapped form.nwrapped-str: Wraps a string with start/end delimiters.nemit-unit: Emits a unit.nemit-internal,emit-internal-str: Emits internal forms or strings.nemit-pre,emit-post,emit-prefix,emit-postfix: Emits operators before/after/prefix/postfix to arguments.nemit-infix,emit-infix-default,emit-infix-pre,emit-infix-if-single,emit-infix-if: Emits infix expressions.nemit-between: Emits a raw symbol between two elements.nemit-bi: Emits a binary infix operator.nemit-assign: Emits an assignment.nemit-return-do,emit-return-base,emit-return: Emits return statements.nemit-with-global: Emits a global variable.nemit-symbol-classify: Classifies a symbol.nemit-symbol-standard: Emits a standard symbol.nemit-symbol: Emits a symbol.nemit-token: Emits a token.nemit-with-decorate: Emits a decorated form.nemit-with-uuid,emit-with-rand: Emits UUIDs or random numbers.ninvoke-kw-parse: Parses keyword arguments for invocation.nemit-invoke-kw-pair,emit-invoke-args,emit-invoke-layout,emit-invoke-raw,emit-invoke-static,emit-invoke-typecast,emit-invoke: Emits function invocations.nemit-new: Emits a constructor call.nemit-class-static-invoke: Emits a static class invocation.nemit-index-entry,emit-index: Emits indexed expressions.nemit-op: Dispatches to the appropriate emitter based on the operation.nform-key: Returns the key associated with a form.nemit-common-loop: The core emission loop.n*emit-common: Emits a string based on grammar.
9.8 hara.lang.base.emit-data (Data Structure Emission)
This sub-namespace handles the emission of various Clojure data structures (maps, vectors, sets, tuples) into their target language equivalents.
Key Functions:
default-map-key: Emits a default map key.nemit-map-key: Emits a map key.nemit-map-entry: Emits a map entry.nemit-singleline-array?: Checks if an array can be emitted on a single line.nemit-maybe-multibody: Emits a multi-line body if necessary.nemit-coll-layout: Lays out a collection.nemit-coll: Emits a collection.nemit-data-standard: Emits standard data.nemit-data: The main function for emitting data forms.nemit-quote: Emits a quoted form.nemit-table-group: Groups table arguments.nemit-table: Emits a table.ntest-data-loop,test-data-emit: Test functions for data emission.
9.9 hara.lang.base.emit-fn (Function Emission)
This sub-namespace handles the emission of function definitions and related constructs, including argument lists, type hints, and function bodies.
Key Functions:
emit-input-default: Emits a default input argument string.nemit-hint-type: Emits a type hint.nemit-def-type: Emits a definition type.nemit-fn-type: Emits a function type.nemit-fn-block: Retrieves block options for a function.nemit-fn-preamble-args: Emits preamble arguments for a function.nemit-fn-preamble: Emits the preamble of a function.nemit-fn: The main function for emitting function templates.ntest-fn-loop,test-fn-emit: Test functions for function emission.
9.10 hara.lang.base.emit-helper (Emission Helper Functions)
This sub-namespace provides various helper functions and constants used throughout the emission pipeline, such as default grammar settings, symbol replacement rules, and argument parsing.
Key Functions:
default-emit-fn: The default emit function.npr-single: Prints a single-quoted string.n+sym-replace+: Symbol replacement rules.n+default+: Default grammar settings.nget-option,get-options: Retrieves grammar options.nform-key-base: Gets the base key for a form.nbasic-typed-args: Parses basic typed arguments.nemit-typed-allowed-args: Emits allowed typed arguments.nemit-typed-args: Emits typed arguments.nemit-symbol-full: Emits a full symbol.nemit-type-record: Formats a type record.
9.11 hara.lang.base.emit-preprocess (Emission Preprocessing)
This sub-namespace handles the preprocessing of Clojure forms before they are emitted, including macro expansion, symbol resolution, and dependency collection.
Core Concepts:
- Dynamic Variables:
*macro-form*,*macro-grammar*,*macro-opts*,*macro-splice*,*macro-skip-deps*.n* Preprocessing Stages:to-input(raw to input forms),to-staging(input to staged forms).
Key Functions:
macro-form,macro-opts,macro-grammar: Accessors for macro context.nwith:macro-opts(macro): Binds macro options.nto-input-form: Processes a raw form into an input form.nto-input: Converts a raw form to an input form.nget-fragment: Retrieves a fragment (macro) from modules.nprocess-namespaced-resolve: Resolves a symbol in the current namespace.nprocess-namespaced-symbol: Processes namespaced symbols.nprocess-inline-assignment: Prepares a form for inline assignment.nto-staging-form: Processes different staging forms.nto-staging: Converts an input form to a staged form, collecting dependencies.nto-resolve: Resolves code symbols without macroexpansion.
9.12 hara.lang.base.emit-special (Special Form Emission)
This sub-namespace handles the emission of special forms, such as !:module (for emitting module contents), !:eval (for evaluating Clojure code at emit time), and !:lang (for embedding code from another language).
Key Functions:
emit-with-module-all-ids: Emits all IDs from a module.nemit-with-module: Emits a module.nemit-with-preprocess: Emits a preprocessed form.nemit-with-eval: Emits an evaluated form.nemit-with-deref: Emits a dereferenced var.nemit-with-lang: Emits an embedded language form.ntest-special-loop,test-special-emit: Test functions for special form emission.
9.13 hara.lang.base.emit-top-level (Top-Level Form Emission)
This sub-namespace handles the emission of top-level forms like defn, def, defglobal, defrun, and defclass.
Key Functions:
transform-defclass-inner: Transforms the body of adefclass.nemit-def: Emits adefstatement.nemit-declare: Emits adeclarestatement.nemit-top-level: The main function for emitting top-level forms.nemit-form: Emits a customisable form.
9.14 hara.lang.base.grammar (Language Grammar Definition)
This sub-namespace defines the structure and semantics of a target language's grammar, including its reserved words, operators, and emission rules.
Core Concepts:
GrammerRecord: Represents a language grammar, containing itstag,emitfunction,structure,reservedwords,bannedforms,highlightkeywords, andmacros.n* Operators (+op-all+): A comprehensive collection of predefined operators (math, compare, logic, control flow, data structures, macros, cross-languagextalkoperations) that can be included in a grammar.
Key Functions:
gen-ops: Generates operators from a namespace.ncollect-ops: Collects all operators.nops-list,ops-symbols,ops-summary,ops-detail: Functions for inspecting operators.nbuild: Selects operators for a grammar.nbuild-min: Builds a minimal grammar.nbuild-xtalk: Builds a grammar with cross-language operators.nbuild:override,build:extend: Modifies an existing grammar.nto-reserved: Converts an operator map to a reserved word map.ngrammar-structure,grammar-sections,grammar-macros: Extracts structural information from a grammar.n*grammar?,grammar: Predicate and constructor forGrammerrecords.
9.15 hara.lang.base.grammar-macro (Macro Transformations)
This sub-namespace provides macro transformations for common Clojure forms (e.g., ->, ->>, when, if, cond, let, case, doto, fn:>) into more basic forms suitable for emission.
Key Functions:
tf-macroexpand: Macroexpands a form.ntf-when: Transformswhento a branch.ntf-if: Transformsifto a branch.ntf-cond: Transformscondto a branch.ntf-let-bind: Transformsletbindings.ntf-case: Transformscaseto a switch.ntf-lambda-arrow: Transforms lambda arrows.ntf-tcond: Transforms ternary conditions.ntf-xor: Transformsxorto a ternary if.ntf-doto: Transformsdototo a sequence ofdooperations.ntf-do-arrow: Transformsdo:>to a function.ntf-forange: Transformsforangeto aforloop.n+op-macro+,+op-macro-arrow+,+op-macro-let+,+op-macro-xor+,+op-macro-case+,+op-macro-forange+: Collections of macro operators.
9.16 hara.lang.base.grammar-spec (Grammar Specification)
This sub-namespace defines the core set of operators and their properties that form the basis of most language grammars. It includes operators for built-in functions, math, comparisons, logic, control flow, and top-level definitions.
Key Functions:
get-comment: Retrieves the comment prefix for a language.nformat-fargs: Formats function arguments.nformat-defn: Formatsdefnforms.ntf-for-index: Transformsfor:indexloops.n+op-builtin+,+op-builtin-global+,+op-builtin-module+,+op-builtin-helper+: Built-in operators.n+op-free-control+,+op-free-literal+: Free control and literal operators.n+op-math+,+op-compare+,+op-logic+,+op-counter+: Math, comparison, logic, and counter operators.n+op-return+,+op-throw+,+op-await+: Return, throw, and await operators.n+op-data-table+,+op-data-shortcuts+,+op-data-range+: Data table, shortcuts, and range operators.n+op-vars+,+op-bit+,+op-pointer+: Variable, bit, and pointer operators.n+op-fn+,+op-block+: Function and block operators.n+op-control-base+,+op-control-general+,+op-control-try-catch+: Control flow operators.n+op-top-base+,+op-top-global+: Top-level operators.n+op-class+: Class-related operators.n+op-for+,+op-coroutine+: For loop and coroutine operators.
9.17 hara.lang.base.grammar-xtalk (Cross-Language Operators)
This sub-namespace defines a set of "cross-talk" (xtalk) operators that provide a common interface for language-agnostic operations, such as object manipulation, type checking, and I/O. These operators are designed to be implemented differently in each target language.
Key Functions:
tf-throw: Transformsthrow.ntf-eq-nil?,tf-not-nil?: Transforms nil checks.ntf-proto-create: Transforms prototype creation.ntf-has-key?: Transforms key existence checks.ntf-get-path,tf-get-key: Transforms property access.ntf-set-key,tf-del-key: Transforms property setting/deletion.ntf-copy-key: Transforms key copying.ntf-grammar-offset,tf-grammar-end-inclusive: Retrieves grammar-specific offset/inclusive settings.ntf-offset-base,tf-offset,tf-offset-rev,tf-offset-len,tf-offset-rlen: Transforms offset calculations.ntf-global-set,tf-global-has?,tf-global-del: Transforms global variable operations.ntf-lu-eq: Transforms lookup equality.ntf-bit-and,tf-bit-or,tf-bit-lshift,tf-bit-rshift,tf-bit-xor: Transforms bitwise operations.n+op-xtalk-core+,+op-xtalk-proto+,+op-xtalk-global+,+op-xtalk-custom+,+op-xtalk-math+,+op-xtalk-type+,+op-xtalk-bit+,+op-xtalk-lu+,+op-xtalk-obj+,+op-xtalk-arr+,+op-xtalk-str+,+op-xtalk-js+,+op-xtalk-return+,+op-xtalk-socket+,+op-xtalk-iter+,+op-xtalk-cache+,+op-xtalk-thread+,+op-xtalk-file+,+op-xtalk-b64+,+op-xtalk-uri+,+op-xtalk-special+: Collections of cross-language operators.
9.18 hara.lang.base.impl (Core Implementation Utilities)
This sub-namespace provides core implementation details and helper functions for the language system, including managing the global library, emit options, and direct code emission.
Key Functions:
with:library(macro): Binds a library as the default.ndefault-library,default-library:reset: Manages the default library.nruntime-library: Retrieves the current runtime library.ngrammar: Retrieves the grammar for a language.nemit-options-raw,emit-options: Prepares emit options.nto-form: Converts input to a form.n%.form(macro): Converts to a form.nemit-bulk?: Checks if a form is a bulk form.nemit-direct: Emits a form directly.nemit-str: Converts a form to an output string.n%.str(macro): Converts to an output string.nemit-as: Emits multiple forms.nemit-symbol: Emits a symbol.nget-entry: Retrieves an entry.nemit-entry: Emits an entry.nemit-entry-deps-collect: Collects entry dependencies.nemit-entry-deps: Emits entry dependencies.nemit-script-imports: Emits script imports.nemit-script-deps: Emits script dependencies.nemit-script-join: Joins script parts.nemit-script: Emits a script with all dependencies.nemit-scaffold-raw-imports: Emits scaffold raw imports.nemit-scaffold-raw: Creates scaffold raw entries.nemit-scaffold-for: Creates scaffold for a module.nemit-scaffold-to: Creates scaffold up to a module.n*emit-scaffold-imports: Creates scaffold to expose native imports.
9.19 hara.lang.base.impl-deps (Dependency Management Implementation)
This sub-namespace provides the implementation details for managing dependencies between modules and entries, including collecting native imports and resolving module links.
Key Functions:
module-import-form,module-export-form,module-link-form: Generates import/export/link forms.nhas-module-form,setup-module-form,teardown-module-form: Generates module lifecycle forms.nhas-ptr-form,setup-ptr-form,teardown-ptr-form: Generates pointer lifecycle forms.ncollect-script-natives: Collects native imported modules.ncollect-script-entries: Collects all entries for a script.ncollect-script: Collects dependencies for a script.ncollect-script-summary: Summarizes script dependencies.ncollect-module-check-options: Checks module options.ncollect-module-ns-select: Selects module namespaces.ncollect-module-directory-form: Collects module directory forms.ncollect-module: Collects information for an entire module.
9.20 hara.lang.base.impl-entry (Entry Implementation)
This sub-namespace provides the implementation details for creating and emitting book entries, including handling metadata, preprocessing, and caching.
Key Functions:
create-common: Creates common entry keys from metadata.ncreate-code-raw: Creates a raw code entry.ncreate-code-base: Creates a base code entry.ncreate-code-hydrate: Hydrates code entries.ncreate-code: Creates a code entry.ncreate-fragment: Creates a fragment entry.ncreate-macro: Creates a macro entry.nwith:cache-none,with:cache-force(macros): Control entry caching.nemit-entry-raw: Emits a raw entry.n+cached-emit-keys+,+cached-keys+: Keys for cached emits.nemit-entry-cached: Emits a cached entry.nemit-entry-label: Emits an entry label.nemit-entry: Emits a given entry.
9.21 hara.lang.base.impl-lifecycle (Lifecycle Implementation)
This sub-namespace provides the implementation details for managing the lifecycle of modules, including emitting setup and teardown scripts.
Key Functions:
emit-module-prep: Prepares a module for emission.nemit-module-setup-concat,emit-module-setup-join,emit-module-setup-native-arr,emit-module-setup-link-arr,emit-module-setup-raw,emit-module-setup: Functions for emitting module setup code.nemit-module-teardown-concat,emit-module-teardown-join,emit-module-teardown-raw,emit-module-teardown: Functions for emitting module teardown code.
9.22 hara.lang.base.library (Library Management)
This sub-namespace defines the core Library record and provides functions for managing a collection of language books and their modules/entries. It handles snapshot management and bulk operations.
Key Functions:
wait-snapshot: Waits for the current snapshot to be ready.nwait-apply: Applies a function to the library state when the task queue is empty.nwait-mutate!: Mutates the library state once the task queue is empty.nget-snapshot: Retrieves the current snapshot.nget-book,get-book-raw: Retrieves a book from the library.nget-module,get-entry: Retrieves a module or entry from the library.nadd-book!,delete-book!: Adds or deletes a book.nreset-all!: Resets the library.nlist-modules,list-entries: Lists modules or entries.nadd-module!,delete-module!,delete-modules!: Adds or deletes modules.nlibrary-string: Returns a string representation of the library.nlibrary?,library:create,library: Predicate and constructors forLibraryrecords.nadd-entry!,add-entry-single!,delete-entry!: Adds or deletes entries.n*install-module!,install-book!,purge-book!: Installs modules or books.
9.23 hara.lang.base.library-snapshot (Library Snapshot Management)
This sub-namespace defines the Snapshot record and provides functions for managing immutable snapshots of the library's state, enabling efficient versioning and merging of language definitions.
Key Functions:
get-deps: Retrieves dependencies from a snapshot.nsnapshot-string: Returns a string representation of a snapshot.nsnapshot?,snapshot: Predicate and constructor forSnapshotrecords.nsnapshot-reset: Resets a snapshot.nsnapshot-merge: Merges two snapshots.nget-book-raw,get-book: Retrieves a book from a snapshot.nadd-book: Adds a book to a snapshot.nset-module,delete-module,delete-modules: Manages modules in a snapshot.nlist-modules,list-entries: Lists modules or entries in a snapshot.nset-entry,set-entries,delete-entry,delete-entries: Manages entries in a snapshot.ninstall-check-merged: Checks for merged books.ninstall-module-update,install-module: Updates or installs a module.ninstall-book-update,install-book: Updates or installs a book.
9.24 hara.lang.base.manage (Language Management Tasks)
This sub-namespace provides high-level tasks for managing language definitions, modules, and entries, including overviews, purging, and linting.
Key Functions:
lib-overview-format,lib-overview: Formats and displays a library overview.nlib-module-env: Compiles the module task environment.nlib-module-filter: Filters modules.nlib-module-overview-format,lib-module-overview: Formats and displays a module overview.nlib-module-entries-format-section,lib-module-entries-format,lib-module-entries: Formats and displays module entries.nlib-module-purge-fn,lib-module-purge: Purges modules.nlib-module-unused-fn,lib-module-unused: Lists unused modules.nlib-module-missing-line-number-fn,lib-module-missing-line-number: Lists modules with missing line numbers.nlib-module-incorrect-alias-fn,lib-module-incorrect-alias: Lists modules with incorrect aliases.
9.25 hara.lang.base.pointer (Language Pointers)
This sub-namespace defines the Pointer record, which acts as a reference to a code entry within a specific language runtime. Pointers enable dynamic invocation and introspection of code across different languages.
Key Functions:
with:clip,with:print,with:print-all,with:rt-wrap,with:rt,with:input,with:raw(macros): Control pointer behavior.nget-entry: Retrieves the library entry for a pointer.nptr-tag: Creates a tag for a pointer.nptr-deref: Dereferences a pointer.nptr-display: Displays a pointer.nptr-invoke-meta: Prepares metadata for pointer invocation.nrt-macro-opts: Creates macro options for a runtime.nptr-invoke-string: Emits the invocation string for a pointer.nptr-invoke-script: Emits a script for a pointer.nptr-intern: Interns a pointer into the workspace.nptr-output-json,ptr-output: Handles pointer output.n*ptr-invoke: Invokes a pointer.
9.26 hara.lang.base.registry (Language Registry)
This sub-namespace defines a global registry (+registry+) that maps language contexts and runtime keys to their corresponding Clojure namespaces, enabling dynamic loading and instantiation of language runtimes.
Core Concepts:
+registry+: An atom storing a map of[lang runtime-key]to Clojure namespace symbols.
9.27 hara.lang.base.runtime (Language Runtimes)
This sub-namespace defines the RuntimeDefault record, which serves as a base implementation for language runtimes. It provides default behaviors for code evaluation, pointer handling, and lifecycle management.
Core Concepts:
RuntimeDefaultRecord: A base runtime implementation that can be extended or proxied.nIContextProtocol: Implemented by runtimes for raw code evaluation, pointer initialization, tag retrieval, dereferencing, display, and invocation.nIComponentProtocol: Implemented by runtimes for lifecycle management (start, stop, kill).
Key Functions:
default-tags-ptr,default-deref-ptr,default-invoke-ptr,default-init-ptr,default-display-ptr,default-raw-eval,default-transform-in-ptr,default-transform-out-ptr: Default implementations forIContextmethods.nrt-default-string: Returns a string representation of a default runtime.nrt-default?,rt-default: Predicate and constructor forRuntimeDefaultrecords.ninstall-lang!,install-type!: Installs language definitions and runtime types.nreturn-format-simple,return-format,return-wrap-invoke,return-transform: Functions for formatting return values.ndefault-invoke-script: Default script invocation.ndefault-lifecycle-prep: Prepares options for lifecycle management.ndefault-scaffold-array,default-scaffold-setup-for,default-scaffold-setup-to,default-scaffold-imports: Functions for scaffolding.ndefault-lifecycle-fn: Constructs a lifecycle function.ndefault-has-module?,default-has-ptr?,default-setup-ptr,default-teardown-ptr: Default lifecycle functions for modules and pointers.ndefault-setup-module-emit,default-setup-module-basic,default-teardown-module-basic,default-setup-module,default-teardown-module: Default module setup/teardown functions.n*multistage-invoke,multistage-setup-for,multistage-setup-to,multistage-teardown-for,multistage-teardown-at,multistage-teardown-to: Multistage lifecycle functions.
9.28 hara.lang.base.runtime-proxy (Runtime Proxy)
This sub-namespace defines a proxy mechanism for language runtimes, allowing one runtime to delegate its operations to another. This is useful for creating aliases or for adding layers of functionality.
Key Functions:
rt-proxy-string: Returns a string representation of a runtime proxy.nproxy-get-rt: Retrieves the redirected runtime.nproxy-raw-eval,proxy-init-ptr,proxy-tags-ptr,proxy-deref-ptr,proxy-display-ptr,proxy-invoke-ptr,proxy-transform-in-ptr,proxy-transform-out-ptr: Proxy implementations forIContextmethods.n*proxy-started?,proxy-stopped?,proxy-remote?,proxy-info,proxy-health: Proxy implementations forIComponentmethods.
9.29 hara.lang.base.script (Scripting and Runtime Control)
This sub-namespace provides high-level macros and functions for defining and controlling language scripts and their associated runtimes. It includes mechanisms for installing languages, managing annexes, and executing code in different contexts.
Core Concepts:
scriptMacro: The primary macro for defining a language script, installing its module, and setting up its runtime.n Annexes: A mechanism for extending a language with additional runtimes or configurations.n!Macro: A convenient macro for switching between active annex runtimes and executing code within them.
Key Functions:
install: Installs a language book and its runtime.nscript-ns-import: Imports namespaces for a script.nscript-macro-import: Imports macros for a script.nscript-fn-base,script-fn: Base functions for script setup.nscript(macro): Defines a language script.nscript-test-prep,script-test: Prepares and runs test scripts.nscript-(macro): Defines a test script.nscript-ext,script+(macro): Extends a script with additional runtimes (annexes).nscript-ext-run: Executes code in an annex runtime.n!(macro): Executes code in a specified annex runtime.nannex:start,annex:get,annex:stop,annex:start-all,annex:stop-all,annex:restart-all,annex:list: Functions for managing annexes.
9.30 hara.lang.base.script-annex (Script Annex Management)
This sub-namespace provides the implementation for managing "annexes," which are extensions to language scripts that allow for dynamic runtime switching and configuration.
Key Functions:
rt-annex-string: Returns a string representation of a runtime annex.nrt-annex?,rt-annex:create: Predicate and constructor forRuntimeAnnexrecords.nannex-current,annex-reset: Manages the current annex.nget-annex: Retrieves the current annex.nclear-annex: Clears all runtimes in an annex.nget-annex-library,get-annex-book: Retrieves the library or book from an annex.nadd-annex-runtime,get-annex-runtime,remove-annex-runtime: Manages runtimes in an annex.nregister-annex-tag,deregister-annex-tag: Registers or deregisters annex tags.nstart-runtime: Starts a runtime in an annex.n*same-runtime?: Checks if two runtimes are the same.
9.31 hara.lang.base.script-control (Script Runtime Control)
This sub-namespace provides functions for controlling language runtimes, including getting, stopping, and restarting them, as well as executing one-shot evaluations.
Key Functions:
script-rt-get: Retrieves a language runtime.nscript-rt-stop,script-rt-restart: Stops or restarts a runtime.nscript-rt-oneshot-eval,script-rt-oneshot: Executes one-shot evaluations.
9.32 hara.lang.base.script-def (Script Definition Helpers)
This sub-namespace provides helper functions for defining script-related templates and macros.
Key Functions:
tmpl-entry: Creates templates for various argument types.n*tmpl-macro: Creates templates for macros.
9.33 hara.lang.base.script-lint (Script Linting)
This sub-namespace provides a basic linter for language scripts, checking for unused variables, unknown symbols, and other potential issues.
Key Functions:
get-reserved-raw,get-reserved: Retrieves reserved symbols from a grammar.ncollect-vars: Collects all variables in a form.ncollect-module-globals: Collects global symbols from a module.ncollect-sym-vars: Collects symbols and variables.nsym-check-linter: Checks the linter.nlint-set,lint-clear,lint-needed?: Manages linting settings.nlint-entry: Lints a single entry.
9.34 hara.lang.base.script-macro (Script Macro Interning)
This sub-namespace provides functions for interning language-specific macros and top-level forms into the Clojure environment, making them available for use in scripts.
Key Functions:
body-arglists: Extracts arglists from a function body.nintern-in: Interns a macro.nintern-prep: Prepares module and form metadata for interning.nintern-def$-fn,intern-def$: Internsdef$fragments.nintern-defmacro-fn,intern-defmacro: Internsdefmacroforms.ncall-thunk: Calls a thunk with pointer output control.nintern-!-fn,intern-!: Interns free pointer macros.nintern-free-fn,intern-free: Interns free pointers.nintern-top-level-fn,intern-top-level: Interns top-level functions.nintern-macros: Interns all macros from a grammar.nintern-highlights: Interns highlight macros.nintern-grammar: Interns a grammar's macros into the namespace.nintern-defmacro-rt-fn,defmacro.!(macro): Defines runtime language macros.
9.35 hara.lang.base.util (Language Utilities)
This sub-namespace provides various utility functions for working with language-related symbols, contexts, and pointers.
Key Functions:
sym-id,sym-module,sym-pair,sym-full,sym-default-str,sym-default-inverse-str: Functions for manipulating symbols.nhashvec?,doublevec?: Predicates for vector types.nlang-context: Creates a language context keyword.nlang-rt-list,lang-rt: Lists and retrieves language runtimes.nlang-rt-default: Retrieves the default runtime function.n*lang-pointer: Creates a language pointer.
9.36 hara.lang.base.workspace (Workspace Management)
This sub-namespace provides functions for managing the language workspace, including emitting modules, printing module contents, and controlling runtime lifecycles.
Key Functions:
rt-resolve: Resolves a runtime.nsym-entry,sym-pointer: Retrieves entries or pointers from symbols.nmodule-entries: Retrieves module entries.nemit-ptr: Emits a pointer as a string.nptr-clip,ptr-print: Copies or prints pointer text.nptr-setup,ptr-teardown: Sets up or tears down a pointer.nptr-setup-deps,ptr-teardown-deps: Sets up or tears down pointer dependencies.nemit-module: Emits an entire module.nprint-module: Prints a module.nrt:module,rt:module-purge: Manages module purging.nrt:inner: Retrieves the inner client for a shared runtime.nrt:restart: Restarts a shared runtime.nmultistage-tmpl: Template for multistage functions.n*intern-macros: Interns macros from one namespace to another.
9.37 hara.lang.interface.type-notify (Notification Server)
This sub-namespace implements a notification server that allows language runtimes to send messages back to the Clojure host, enabling real-time feedback and event handling.
Key Functions:
has-sink?,get-sink,clear-sink: Manages notification sinks.nadd-listener,remove-listener: Manages listeners for sinks.nget-oneshot-id,remove-oneshot-id,clear-oneshot-sinks: Manages one-shot notification IDs.nprocess-print,process-capture,process-message: Processes incoming messages.nhandle-notify-http,start-notify-http,stop-notify-http: Manages HTTP notification server.nhandle-notify-socket,start-notify-socket,stop-notify-socket: Manages Socket notification server.nstart-notify,stop-notify: Starts or stops both notification servers.nnotify-server-string: Returns a string representation of the notification server.nNotifyServer(defimpl record): The concrete record type for the notification server.nnotify-server:create,notify-server: Constructors for the notification server.ndefault-notify,default-notify:reset: Manages the default notification server.n*watch-oneshot: Watches for a one-shot notification.
9.38 hara.lang.interface.type-shared (Shared Runtime Management)
This sub-namespace provides mechanisms for managing shared language runtimes, allowing multiple clients to share a single runtime instance.
Key Functions:
get-groups: Retrieves all shared groups.nget-group-count,update-group-count: Manages group counts.nget-group-instance,set-group-instance,update-group-instance: Manages group instances.nrestart-group-instance: Restarts a group instance.nremove-group-instance: Removes a group instance.nstart-shared,stop-shared,kill-shared: Lifecycle functions for shared runtimes.nwrap-shared: Wraps a function to operate on a shared runtime.nrt-shared-string: Returns a string representation of a shared runtime.nSharedRuntime(defimpl record): The concrete record type for a shared runtime.nrt-shared:create,rt-shared: Constructors for shared runtimes.nrt-is-shared?: Checks if a runtime is shared.n*rt-get-inner: Retrieves the inner runtime.
9.39 hara.lang.model. (Language Specifications)
These sub-namespaces define the specific grammars and templates for various target languages, including Bash, C, GLSL, JQ, JavaScript, Lua, Python, R, Rust, and Scheme. They extend the base grammar with language-specific syntax, operators, and emission rules.
Core Concepts:
- Language-Specific Grammars: Each
spec_<lang>.cljfile defines a+grammar+for its respective language, built uponhara.lang.base.grammar.n Language-Specific Templates: Eachspec_<lang>.cljfile defines a+template+for its respective language, customizing emission rules for data structures, blocks, and tokens.n Cross-Talk (XTalk) Operators: Thespec_xtalk.cljandspec_xtalk/fn_<lang>.cljfiles define cross-language operators that provide a common interface for operations that are implemented differently in each target language.
Key Functions (examples from spec_js.clj, spec_lua.clj, spec_python.clj, spec_r.clj, spec_rust.clj, spec_bash.clj, spec_glsl.clj, spec_scheme.clj, spec_jq.clj):
+features+: Defines language-specific operators and their emission rules.n+template+: Customizes the emission template for the language.n+grammar+: The final grammar for the language.n+meta+: Language-specific metadata (e.g., module import/export functions).n+book+: The language book, containing its grammar and meta.n+init+: Installs the language into the system.n Language-specific transformation functions (e.g.,js-regex,lua-map-key,python-defn,r-token-boolean,rst-typesystem,bash-quote-item): Implement custom emission logic for various forms and data types.
9.40 hara.lang.strict.basestate (Strict Mode State)
This sub-namespace likely provides state management for a "strict mode" within the language system, though its contents are minimal in the provided files.
9.41 Usage Pattern:
The hara.lang module is the cornerstone of the foundation-base project, enabling:
- Polyglot Development: Write code once in Clojure and deploy it to multiple target languages.n Unified Tooling: Use a single set of tools for code generation, testing, and runtime management across different languages.n Metaprogramming: Programmatically generate and transform code for various platforms.n Language Experimentation: Easily define and experiment with new DSLs and language features.n Runtime Agnosticism: Abstract away the complexities of interacting with different execution environments.
By providing a powerful and extensible framework for language definition and code generation, hara.lang empowers developers to build highly flexible and adaptable software systems.