Skip to content

DeltaScript – Native function semantics

Jordan Bunke edited this page May 18, 2024 · 13 revisions

This page outlines the semantics of the properties, scoped functions (functions called on a "parent" expression, henceforth referred to as their "scope") and global functions that are supported by the DeltaScript base language. Functions with constraints will throw runtime errors if they are passed arguments that violate their constraints.

Type signatures

// property
(type scope).property_name -> type

// scoped function; returns a value
(type scope).func_name(type(s) and ID(s) of valid arguments) -> return type

// scoped function; void return
(type scope).func_name(type(s) and ID(s) of valid arguments);

// global function; returns a value
func_name(type(s) and ID(s) of valid arguments) -> return type

Wildcards

  • T and U represents a wildcard / generic type. The use of U is for cases where T has already been used and U is a stand-in for a type that must not necessarily be the same as T. Repeated use of T, as in scope.add(), means that each instance of T must be the same type.
  • N represents a numeric type i.e. either int or float
  • C<T> represents a collection type: any of array T[], list T<> or set T{} where T represents the type of the collection's elements
    • O<T> represents an ordered collection type; so the same scope as C<T> but excluding sets (T{})
    • D<T> represents a dynamic collection type that can grow and shrink; so the same scope as C<T> but excluding arrays (T[])

Properties

Properties are considered inherent, immutable attributes of their scopes. This is reflected in the syntax by not being followed by opening and closing parentheses, as would be the case for functions with no arguments.

RGBA color channel - scope.red, scope.green, scope.blue, scope.alpha, scope.r, scope.g, scope.b, scope.a

(color scope).red -> int

Returns the 8-bit value of the R, G, B or A channel of the color scope. This value will range from 0 to 255.

Notes:

  • The one-letter variants are merely syntactical shorthand equivalents of the full property names and can be used interchangeably
  • scope.red is used in the type signature as an example, but all RGBA color channels follow the same syntax and semantics

Image bounds - scope.width, scope.height, scope.w, scope.h

(image scope).width -> int

Returns the width or height of the image scope in pixels.

Notes:

  • The one-letter variants are merely syntactical shorthand equivalents of the full property names and can be used interchangeably
  • scope.width is used in the type signature as an example, but scope.height follows the same syntax and semantics

Scoped functions

Like properties, scoped functions are called on expressions of certain types. They take the form scope.func(args), where scope is the expression they are called on, func is the name of the scoped function, and args are its arguments.

Add to collection -scope.add()

// 1. add element to list at index i
(T<> scope).add(T element, int i);

// 2. generic add element to collection
(D<T> scope).add(T element);
  1. element is added to the list scope at the index i.
  2. element is added to the growable collection scope. If scope is a list, element is appended to end of the list.

Constraints:

  1. i >= 0 && i <= #|scope

Remove from collection - scope.remove()

(T<> scope).remove(int i);

The element in the list scope at index i will be removed from the list.

Constraints:

i >= 0 && i < #|scope

Define map / dictionary entry - scope.define()

({T:U} scope).define(T k, U v);

A new mapping is created in the map scope that maps the key k to v. If an entry with the same key already existed, its value is overridden with v.

Draw image on canvas - scope.draw()

(image scope).draw(image img, int x, int y);

Draws the image img onto the image scope with the top-left corner of img at the coordinate x,y.

Set single pixel - scope.dot()

(image scope).dot(color c, int x, int y);

Sets the color of of the pixel specified by the coordinates (x,y) to the color c in the image scope.

Constraints:

0 <= x < scope.w && 0 <= y < scope.h

Draw line - scope.line()

(image scope).line(color c, float breadth, int x1, int y1, int x2, int y2);

Draws a line with a breadth of breadth pixels onto the image scope from (x1, y1) to (x2, y2).

Constraints:

breadth >= 0.0

Fill rectangle - scope.fill()

(image scope).fill(color c, int x, int y, int width, int height);

Fills the rectangular pixel area specified by the top-left coordinate (x,y) and the dimensions width x height with the color c in the image scope.

Constraints:

width > 0 && height > 0

Data structure contains element - scope.has()

// 1. collection contains element
(C<T> scope).has(T element) -> bool

// 2. map contains key
({T:U} scope).has(T key) -> bool
  1. Returns true if the collection scope contains the element element, otherwise false.
  2. Returns true if the map scope contains the key key, otherwise false.

Look up in map / dictionary - scope.lookup()

({T:U} scope).lookup(T key) -> U

Returns the value associated with the key key in the map scope.

Constraints:

scope.has(key)

Get set of map / dictionary keys - scope.keys()

({T:U} scope).keys() -> T{}

Returns the set of keys in the map scope.

Image subsection - scope.section()

(image scope).section(int x, int y, int width, int height) -> image

Returns a subsection of the image scope specified by the top-left pixel coordinate (x,y) and the dimensions width x height pixels.

Constraints:

width > 0 && height > 0

Get color at pixel coordinate - scope.pixel()

(image scope).pixel(int x, int y) -> color

Returns the color of the pixel at the coordinate (x,y) in the image scope.

Constraints:

0 <= x < scope.w && 0 <= y < scope.h

Character at index - scope.at()

(string scope).at(int i) -> char

Returns the character at the index i in the string scope.

Constraints:

0 <= i < #|scope

Substring - scope.sub()

(string scope).sub(int beg, int endEx) -> string

Returns the substring of scope specified by the beginning index beg and the end index endEx.

Note that endEx is the index of the first character NOT to be included in the substring. This way, a substring that starts at some arbitrary index i and includes the remainder of the string str can be specified by str.sub(i, #|str).

Constraints:

beg < endEx && 0 <= beg < #|scope && 0 < end <= #|scope

Global functions

Global functions take the form func(args), where func is the name of the global function and args are its arguments.

Define color from RGB values - rgb()

rgb(int r, int g, int b) -> color

Returns a color with the RGB color channel values r, g and b. The color is opaque; i.e. the color has an alpha channel value of 255/0xff. You can read more about the RGB color model here.

Constraints:

0 <= r <= 255 && 0 <= g <= 255 && 0 <= b <= 255

Define color from RGBA values - rgba()

rgba(int r, int g, int b, int a) -> color

Returns a color with the RGBA color channel values r, g, b and a.

Constraints:

0 <= r <= 255 && 0 <= g <= 255 && 0 <= b <= 255 && 0 <= a <= 255

Absolute value / magnitude - abs()

abs(N num) -> N

Returns the absolute value i.e. the magnitude of num.

Minimum and maximum - min(), max()

// 1. minimum of two numbers
min(N a, N b) -> N

// 2. minimum of collection
min(C<N> collection) -> N
  1. min() returns the minimum of a and b.
  2. min() returns the minimum i.e. lowest signed numerical element in the collection

max() follows via analogy.

Clamp / bounding - clamp()

clamp(N min, N v, N max) -> N

If v < min, clamp() returns min. If v > max, clamp() returns max. Otherwise, clamp() returns v.

Random - rand()

// 1. random float 0.0 - 1.0
rand() -> float

// 2. random number in range [min, maxEx)
rand(N min, N maxEx) -> N
  1. Returns a random floating-point number 0.0 <= r < 1.0
  2. Returns a random value ranging from min (inclusive) to maxEx (exclusive). For example rand(2, 6) can return 2, 3, 4 or 5.

rand(), as well as other randomness functions in DeltaScript like prob() and flip_coin(), generate random numbers using the underlying pseudorandom number generation algorithm used by an instance of the Random class in the Java standard library.

Probability - prob()

prob(float p) -> bool

prob() compares its argument p against a random floating-point number ranging from 0.0 to 1.0 (but never exactly 1.0) and returns true if p is greater than that number, and false if it is not. That way, prob(0.0) is always false and prob(1.0) is always true.

Note that while the interpreter does not enforce constraints on p, a value of p of less than 0.0 will always be evaluated to false, and a value of p of greater than 1.0 will always be evaluated to true.

Flip coin i.e. 50% probability - flip_coin()

// 1. simple boolean
flip_coin() -> bool

// 2. returns one of two arguments
flip_coin(T heads, T tails) -> T
  1. Flips a coin with an equal probability of heads or tails, and no other possible outcome. flip_coin() is the equivalent of prob(0.5).
  2. flip_coin(heads, tails) is a syntactical shorthand for the longer ternary expression flip_coin() ? heads : tails.

Image from file path - from()

from(string path) -> image

Imports an image from an image file at the absolute file path specified by path.

Constraints:

path must be a valid absolute file path that corresponds with a static raster image file format (PNG, JPEG, etc.)

Blank image of set bounds - blank()

blank(int width, int height) -> image

Creates a new transparent image with bounds/dimensions specified by width x height pixels.

Constraints:

width > 0 && height > 0

Texture color replace - tex_col_repl()

tex_col_repl(image img, image lookup, image replace) -> image

Returns an image of the same dimensions as img that consists of img's non-transparent pixels having had their color replaced. Every non-transparent pixel in lookup should have a unique color. Every pixel color in img should then map to a pixel coordinate in lookup. replace should be of the same dimensions as lookup. Thus, the color replacement in img first finds the coordinate of the color that has been detected in lookup, and samples the color at that same coordinate in replace for the replacement.

You can find the replacement algorithm here.

Constraints:

lookup.width == replace.width && lookup.height == replace.height

Generate lookup texture - gen_lookup()

gen_lookup(image img, bool vertical) -> image

Generates a naive lookup texture based on the contents of img. For every non-transparent pixel in img, the lookup texture assigns a unique color. The resulting lookup texture will appear striped. A vertical value of true will result in vertical striping, while a value of false will result in horizontal striping.

You can find the lookup generation algorithm here.

Clone this wiki locally