Skip to content

Instantly share code, notes, and snippets.

@passcod
Last active October 6, 2021 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save passcod/f58eda5f99d2c9366333034832b53cbf to your computer and use it in GitHub Desktop.
Save passcod/f58eda5f99d2c9366333034832b53cbf to your computer and use it in GitHub Desktop.
HUG language

HUG

A function call syntax for KDL.

HUG is several things:

  • A strict KDL superset: all KDL is valid HUG.
  • A syntax and spec for calling functions in KDL documents.
  • A standard library of HUG functions.

Name

HUG Is Not An Acronym

  • it's pronounced like "hug"
  • the file extension is .hug
  • the plural is HUGs

Syntax

Format: \ NAME [ [ INPUT ] ], where:

  • NAME is a KDL bare identifier
  • INPUT is optional
  • the [] square brackets are required regardless
  • whitespace may surround the INPUT

Function calls may be preceded by a type annotation.

The INPUT is either:

  • a document
  • a heterogenous list of values or function calls, separated by commas

A function call can be present in the position of:

  • a node
  • a value

A function call cannot be:

  • the name of a node
  • the name of a property
  • a type annotation

There are functions in the standard library to provide for usecases which would need these.

As bare identifiers cannot contain \ nor [], there is no KDL syntax conflict.

Evaluation

There are two modes:

  • partial application evaluates a HUG document as far as possible, and outputs either:

    • a KDL document (when fully resolved), or
    • a HUG document (when partially resolved), with any unresolved functions left in.
  • erroring application does the same as partial application, but produces errors for any leftover/unresolved functions

Arguments

Function calls are passed these arguments:

  • The input document or list, as defined above.
  • The type annotation on the function call, if present.
  • The output context, as one of:
    • Node (1)
    • Value (2)
    • Input (3)

Application

A function is always only called with plain values: all function calls within its input must be fully resolved.

example attribute {
    (lucky)\sum[
        1, 2, 3,
        \double[2]
    ]
    
    \unknown[]
}

In the example above:

  1. double is called with arguments: input: [Value(2)], type: None, context: Input
  2. sum is called with arguments: input: [Value(1), Value(2), Value(3), Value(4)], type: Some(lucky), context: Node
  3. unknown is not a known function, and is left in place
  4. The document resolves to:
    example attribute {
        (lucky)"4"
        \unknown[]
    }
    
  5. In erroring mode, the following error is emitted: "unresolved function \unknown[] at line 7:4".

A function can either:

  • succeed, and output as below;
  • not apply, and remain as an unapplied function call;
  • error.

Output

A function can output:

  • a document
  • a function call
  • a single value
  • a heterogenous list of values or function calls

However, some output types are restricted by the context argument:

  • with context: Node, only documents and function calls can be produced;
  • with context: Value, only single values and function calls can be produced.

Outputs are merged into their surroundings in different ways. Generally, the output of a function call replaces it as if it had been written in the call's place. Except:

  • with context: Node and a document output: all top-level nodes in the document are inserted in the place of the function call.
  • with context: Input and a list of values output: the list is unpacked (1, 2, \id[3, 4], 5 resolves to 1, 2, 3, 4, 5).

Standard library

TODO

\base64_decode[string] -> string

Takes a string of Base64 data. The string may span multiple lines: inner whitespace will be ignored. The Base64 alphabet is as in IETF RFC3548.

quote text=\base64_decode["
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24
gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2
YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZ
WRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=
"]

// resolves to:
quote text=\base64_decode["TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="]

// or (implementation dependent):
quote text="Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."

\base64_encode[string] -> string

Takes a string and returns its Base64 representation. The Base64 alphabet is as in IETF RFC3548. The output will have no newlines or whitespace.

quote text=\base64_encode["Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."]

// resolves to:
quote text="TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
@passcod
Copy link
Author

passcod commented Oct 6, 2021

Revised/simplified on 7 October 2021, given changes in KDL 1.0.0:

  • no more additional primitives (use KDL type annotations)
  • no more type system
  • no more placeholders and variables
  • only functions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment