# metalthea

> Universal metaprogramming language to craft it yourself

Latest version **0.4.4** (published 2021-04-05) · MIT license · 0 weekly downloads

## Install

```sh
npm install metalthea
pnpm add metalthea
yarn add metalthea
bun add metalthea
```

Provides the command `metalthea`.

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.4.4 |
| Published | 2021-04-05 |
| First published | 2019-03-06 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 4 |
| Unpacked size | 54.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Lucien Boudy |
| Maintainers | hatscat |
| Keywords | language, meta, metaprogramming, metalanguage, macro, functional, lisp, s-expression, compiler |

## Links

- npm: https://www.npmjs.com/package/metalthea
- Repository: https://gitlab.com/Hatscat/metalthea
- npm.io page: https://npm.io/package/metalthea

## Dependencies (4)

- [meow](https://npm.io/package/meow.md) ^9.0.0
- [globby](https://npm.io/package/globby.md) ^11.0.3
- [chokidar](https://npm.io/package/chokidar.md) ^3.5.1
- [make-dir](https://npm.io/package/make-dir.md) ^3.1.0

## Alternatives

- [@openai/codex-sdk](https://npm.io/package/@openai/codex-sdk.md) — 731.4K weekly downloads
- [babel-plugin-transform-react-jsx](https://npm.io/package/babel-plugin-transform-react-jsx.md) — 565.0K weekly downloads
- [babel-helper-remove-or-void](https://npm.io/package/babel-helper-remove-or-void.md) — 508.5K weekly downloads
- [@pnpm/store-controller-types](https://npm.io/package/@pnpm/store-controller-types.md) — 186.9K weekly downloads
- [react-native-signature-canvas](https://npm.io/package/react-native-signature-canvas.md) — 155.6K weekly downloads

## Recent versions

- 0.4.4 (latest) — 2021-04-05
- 0.4.3 — 2021-04-04
- 0.4.2 — 2021-04-02
- 0.4.1 — 2021-03-22
- 0.4.0 — 2019-03-24
- 0.3.0 — 2019-03-24
- 0.2.1 — 2019-03-20
- 0.2.0 — 2019-03-09
- 0.1.3 — 2019-03-09
- 0.1.2 — 2019-03-08
- 0.1.1 — 2019-03-06

## README

# Metalthea

A universal metaprogramming language to build it yourself!

## Features

* Metalthea is a metaprogramming language designed to generates code in-line using text manipulation and substitution at compile-time, like a macro system, for any programming language.
* Metalthea has no built-in function, nor arithmetic operations, nor control structure, you have to implement that yourself, as you want it to work, in Javascript.
* Metalthea has the parenthesized syntax of S-expressions (like the Lisp programming language).

## Basic API Usage
```javascript
const metalthea = require("metalthea");

const { value: output, syntaxTree, errorLogs } = metalthea.compileSourceCode('(add 1 2 3)', {
  add: (...args) => args.reduce((a, b) => `${a} + ${b}`),
});

// output == "1 + 2 + 3"
```

## Program examples

* A hello world *(in the middle of a text)*:
```javascript
// in source code:
"you can write anything before Metalthea..."
(log (str.join "Hello" "World" "!"))
"...and after too"

// in language implementation
const execCtx = {
  log: function(str) {
    return `console.log(${ str });`;
  },
  str: {
    join: function(...args) {
      return args.join(' ');
    }
  }
}

// the result in the output file:
"you can write anything before Metalthea..."
console.log("Hello World!");
"...and after too"
```

* Other examples in [`test/`](https://gitlab.com/Hatscat/metalthea/blob/master/test/):
  * [integration test](https://gitlab.com/Hatscat/metalthea/blob/master/test/integration/)
  * [unit tests cases](https://gitlab.com/Hatscat/metalthea/blob/master/test/programCases.js)
  * [execution context for unit tests](https://gitlab.com/Hatscat/metalthea/blob/master/test/executionContext.js)

## Why?

* To add macro features in your usual language.
* To use cool language features you want to work with _(strong typing, pattern matching, tuples, etc.)_.
* To transpile one source code to multiple programming language.
* To use as a codegolfing tool.

## Syntax

The Metalthea syntax is close to Lisp S-expressions:
* an Expression is either an Atom or a List of Expressions.
* a List is a matched pair of parentheses, with zero or more Expressions inside it.
* an Atom is either:
  * a base 10 **Number**
    - i.e. `42`, `3.14`, `-1.6`
  * a base 16 **Number**
    - starting with `0x`, can have a decimal part after a dot
    - i.e. `0x2A`, `0x3.2f`, `-0xCC.c`
  * a **String**
    - between double quotes `"`
    - i.e. `""`, `"0"`, `"Hello World!"`
  * a **Boolean**
    - in lowercase
    - i.e. `true`, `false`
  * a **Key**
    - starting with colon `:`
    - i.e. `:i`, `:myVar`, `:$_21`
  * a **Body**
    - either between braces `{}` or between grave accents ``` ` ```
    - i.e. `{1 + 1}`, `{n => n * n}, {)}`, **or** ``` `\n` ```, ``` `substring to complete in js` ```
  * a **Function**
    - i.e. `add`, `str2Int`, `__$log`
  * a **Lazy Node**
    - a node starting with a sharp sign `#`
    - i.e `#`, `#(mul 2)`

*you can check [Grammar RegExp there](https://gitlab.com/Hatscat/metalthea/blob/master/src/grammar.js)*

To separate Expressions you can use either the space character (` `) or a comma (`,`) for the same result, in example:
```lisp
(Map :a 12, :b 36, :c 42)
```

You can also chain expressions with the character `>`, in example:
```lisp
((add 1 1) > sqrt)
```
is the same thing as:
```lisp
(sqrt (add 1 1))
```

## Installation

You need [Node.js](https://nodejs.org) to use Metalthea, so I suggest you to setup a `package.json` in your project, regardless of what are the other programming language(s), with npm:

```sh
npm init
npm install --save-dev metalthea
```
or with yarn:
```sh
yarn init
yarn add --dev metalthea
```

## Configuration

* in `package.json`:

add commands in `"scripts"`:
```json
"metalthea": "metalthea <PATH/TO/EXEC_CTX_FILES> <PATH/TO/INPUT_FILES> <PATH/TO/OUTPUT_DIR>",
"build": "npm run metalthea --verbose && <YOUR BUILD COMMAND>",
"watch": "metalthea --verbose --watch"
```

* in `metalthea.json`:

*TODO (dependency management and custom setup for execution context from multiple sources)*

## CLI Usage

command syntax:
```
metalthea <CTX> <SRC> <TARGET>
```

### Options
```
  --verbose, -v  add logs to stdout
  --syntax-tree, -t  logs the intermediate syntax tree in stdout
  --watch, -w  watch context and source files and re-compile if any change is detected
```

### Examples

If you have configured `package.json` as recommended:
```sh
npm run metalthea --verbose --watch
```
or included in your build flow:
```sh
npm run build
```
or using a shell with Metalthea installed globally *(`npm install -g methathea`)*:
```sh
metalthea src/metalthea src/js dist --verbose --watch
```
or use the [Node API](https://gitlab.com/Hatscat/metalthea/blob/master/API.md) from your Node.js project.

## FAQ

* How to use loops and conditions? (_control structure_)
  * Implement it yourself! The easiest way is to craft expression based ones, but you can implement statements as well.
  * i.e. `(if (check :test) "yes!" "no")`, `(for 0,99,1 #(log))`
* There are missing types *(list, array, character, etc.)*!
  * Implement it yourself!
  * i.e. `(Map :x 21, :y -42)`
* How to handle null / undefined ?
  * You can test values in javascript, you can event add a custom Null type if you wish.
  * i.e. `(def :x (if (isNull :a) 0, :a))`
* How to add a comment?
  * For the moment you have to implement it yourself.
  * i.e. `(comment "blaba")`
* How to use arithmetic operations *(+, -, *, /, %)*?
  * Implement it yourself!
  * i.e. `(mul 3 (add 5 4) > sqrt)`
* I need strong typing!
  * Implement it yourself!
  * i.e. `(defTyped (int :n) 42)`
* How to declare variables?
  * For the global scope you can implement it yourself, outside of function scope in javascript.
    * i.e. *(in the execution context javascript file)* `const state = {};`
  * For the local scope you can use the keyword `this` in javascript functions.
    * i.e. `function def(varName, value) { this[varName] = value; }`
* How to use Lazy Node *(`#`)*?
  * as a function from javascript.
  * you can store it like any variable, i.e. `(def :double #(mul 2))`.
  * you can pass arguments while executing a Lazy Node, like for other nodes.
  i.e.:
```javascript
// Metalthea program:  (for 0,3,1 #(js.log) > join)

// javascript context:
const execCtx = {
  for: function(from, to, step, bodyLambda) {
    let result = [];
    for (let i = from; i < to; i += step) {
      result = result.concat(bodyLambda(i, from, to));
    }
    return result;
  },
  log: function(...args) {
    return `console.log(${args.join(",")})`;
  },
  join: function(arr) {
    return arr.join("; ");
  }
};

// output == `console.log(0,0,3); console.log(1,0,3); console.log(args: 2,0,3)`
```

## [Git repository](https://gitlab.com/Hatscat/metalthea)

## [License](https://gitlab.com/Hatscat/metalthea/blob/master/LICENSE)

MIT © [Lucien Boudy](https://gitlab.com/Hatscat)

## ["Contributing" documentation](https://gitlab.com/Hatscat/metalthea/blob/master/CONTRIBUTING.md)

*[in CONTRIBUTING.md file](https://gitlab.com/Hatscat/metalthea/blob/master/CONTRIBUTING.md)*

---
_Source: https://npm.io/package/metalthea · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
