Skip to content

Instantly share code, notes, and snippets.

@branneman
Last active September 16, 2022 17:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save branneman/fe6e988c814dc21a4752561fd5c567b7 to your computer and use it in GitHub Desktop.
Save branneman/fe6e988c814dc21a4752561fd5c567b7 to your computer and use it in GitHub Desktop.
Hogget language specification - https://hogget.org/

Hogget: Philosophy

Elevator pitch

  • Functional programming language
  • Strong typed
  • Dense syntax, everything is an expression
  • Compiles to JavaScript

The Name

A Hogget is a sheep between one and two years of age. Inspired by Ramda, we also like sheep. It's a unique and rememberable name, a short one, it's not yet taken, easily pronounceable, and there's not too many languages that start with an H yet.

Facts

  • Implemented in JavaScript for Node.js
  • File extension: .hgg
  • British English

Hogget: language specification

Types

  • null
  • bool (true or false)
  • int (signed)
  • dec (signed)
  • str (utf-8)
  • enum
  • list (int indexed)
  • obj (string indexed)
  • func

Program

All hogget programs are started by calling the main function, which must be implemented by the user. Example:

let main = => {
  log('the answer is' add(12 30) '\n');
  exit(0);
}

Expressions & Statements

Expressions are language constructs that evaluate into a value and can be nested. Statements are language constructs that don't evaluate into a value and must stand on their own, they are separated with ;.

Comments

// single line comment
let myVar = 42; // inline comment
/* multi
line
comment */

Variables

All variables are immutable. Declare a variable with the let statement, which receives an expression or value.

let myVar = 42;
let myResults = getResults();

Numbers

The rule is simple: if there's a . involved in a number, it's a dec, otherwise it's an int. Whether it's positive or negative doesn't matter.

let answer = 42;
let pi = 3.14;
let cold = -3;

Strings

Strings are delimited with a single quote ('), and are interpolated with ${varName}. Example:

let question = 'What is the answer to everything?';
let answer = 'The answer is ${toStr(42)}';

Enums

let PaymentCardType = enum { MasterCard Maestro Visa };
let myPayment1 = enum(PaymentCardType Visa); // functional access
let myPayment0 = PaymentCardType.Maestro;    // operator access

Lists

let constants = [1.41 2.71 3.14];

Objects

Comma's (,) are fully optional, though they may increase readability when using single line syntax. The formatter will put objects on a single line wih comma's if the line does not exeed 80 characters.

let position = obj { lat: 123.456, lng: 789.321 };
let mapConfig = obj {
  center: obj {
    lat: 123.456
    lng: 789.321
  }
  ratio: "4:3"
  zoom: getDefaultZoom()
};
log(prop("lat" position)); // functional access
log(position.lat);         // operator access

Functions

All functions are expressions and must have an return value (null is valid).

Functions can be defined as one-liners without curly brackets, or as multi line with curly brackets. The last line is the return statement. Specifying arguments is optional.

let myAdd0 = => 12 30;
let myAdd1 = (a b) => add(a b);
let myAdd2 = (a b) => {
  let result = add(a b);
  result;
};

All functions are curried, enabling this kind of programming:

let arr = map(add(12.0) [-27.29 -26.86]);

Hogget: Standard library

Generic

  • log(* ...) -> null - Output a string to the terminal or console. Calls the toStr() function if given anything but a string. Multiple strings are added together, newlines are not automatically inserted.
  • exit(int) -> null: Immediately exits the program, with an exit code.

Logic & Conditionals

  • not(bool) -> bool: Returns the not of it's argument.
  • and(bool bool) -> bool
  • or(bool bool) -> bool
  • xor(bool bool) -> bool
  • if(func func func) -> *: Will call and return either the second or third argument depending on the result of the first.
  • identity(*) -> *: Returns the given argument.
  • eq(* *) -> bool
  • identical(* *) -> bool: Returns true of both arguments are strictly equal.
  • lt() and lte()
  • gt() and gte()

Types

  • type(*) -> string
  • isNull(*) -> bool
  • isBool(*) -> bool
  • isInt(*) -> bool
  • isDec(*) -> bool
  • isStr(*) -> bool
  • isEnum(*) -> bool
  • isOfEnum(enum *) -> bool
  • isList(*) -> bool
  • isObj(*) -> bool
  • isFunc(*) -> bool

Type conversions

  • toBool(*) -> bool
  • toStr(*) -> str
  • toInt(*) -> int
  • toDec(*) -> dec

Numbers

All the arithmetic functions work with either int values or dec values, and will then return the same type. num is used to denote either int or dec.

  • add(num num) -> num
  • subtract(num num) -> num
  • multiply(num num) -> num
  • divide(num num) -> num
  • modulo(num num) -> num: Returns the remainder of the division.
  • pow(num num) -> num
  • product([num]) -> num, implemented as: foldl(multiply, 1)
  • sum([num]) -> num, implemented as: foldl(add, 0))

Strings

  • len(str) -> int: Return length.
  • includes(str) -> bool
  • add(str str) -> str: Add two strings together.
  • capitalise(str) -> str: Uppercase the first character of a string.
  • upper(str) -> str: Uppercase the string.
  • lower(str) -> str: Lowercase the string.
  • slice(int int str) -> str: Slices a string into a subset, given a start index and length (also known as substring).

Lists

  • map(fn list) -> list
  • filter(fn list) -> list
  • foldl(fn * list) -> *: Recursive left-to-right fold (also known as reduce).
  • foldr(fn * list) -> *: Recursive right-to-left fold (also known as reduceRight).
  • chain(fn list) -> list (also known as flatMap).
  • len(list) -> int: Returns the number of items in the list.
  • index(int list) -> *: Returns an item located at given index.
  • find(func list) -> *: Returns an item for which the predicate function returned true.
  • indexOf(* list) -> int: Returns the index for the given item.
  • includes(* list) -> bool: Returns whether the list includes the given item.
  • concat(list list) -> list: Returns the result of concatenating the given lists.
  • flatten(list) -> list: Returns a new list by pulling every item out of it and it's sub-lists.
  • split(str str) -> list
  • join(str list) -> str
  • slice(int int list) -> list: Slices a list into a subset, given a start index and length.
  • fill(int *) -> list
  • sort(func list) -> list
  • cloneShallow(list) -> list
  • cloneDeep(list) -> list

Objects

  • prop(str obj) -> *
  • assoc(str * obj) -> obj
  • cloneShallow(obj) -> obj
  • cloneDeep(obj) -> obj

Functions

  • compose(func func) -> func and compose([func]) -> func: right-to-left function composition.
  • pipe(func func) -> func and pipe([func]) -> func: left-to-right function composition.
  • flip(func) -> func: Returns a new function with it's first two arguments' order reversed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment