metalthea
TypeScript icon, indicating that this package has built-in type declarations

0.4.4 • Public • Published

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

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):
// 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"

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

To separate Expressions you can use either the space character ( ) or a comma (,) for the same result, in example:

(Map :a 12, :b 36, :c 42)

You can also chain expressions with the character >, in example:

((add 1 1) > sqrt)

is the same thing as:

(sqrt (add 1 1))

Installation

You need Node.js 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:

npm init
npm install --save-dev metalthea

or with yarn:

yarn init
yarn add --dev metalthea

Configuration

  • in package.json:

add commands in "scripts":

"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:

npm run metalthea --verbose --watch

or included in your build flow:

npm run build

or using a shell with Metalthea installed globally (npm install -g methathea):

metalthea src/metalthea src/js dist --verbose --watch

or use the Node API 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.:
// 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

License

MIT © Lucien Boudy

"Contributing" documentation

in CONTRIBUTING.md file

Package Sidebar

Install

npm i metalthea

Weekly Downloads

4

Version

0.4.4

License

MIT

Unpacked Size

56.1 kB

Total Files

49

Last publish

Collaborators

  • hatscat