Skip to content

rbuckton/proposal-struct

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Value Types (i.e., 'struct') for ECMAScript

TODO: Replace this with a summary or introduction for your proposal.

Status

Stage: 0
Champion: Ron Buckton (@rbuckton)

For detailed status of this proposal see TODO, below.

Authors

  • Ron Buckton (@rbuckton)

Motivations

TODO: Replace this with motivations and use cases for the proposal.

Prior Art

TODO: Add links to similar concepts in existing languages, prior proposals, etc.

Syntax

struct Point {
  x: i32;
  y: i32;

  offset(dx, dy) { return Point(this.x + dx, this.y + dy); }
  toString() { return `${this.x},${this.y}`; }

  static (Point + Point)  (a, b) { return Point(a.x + b.x, a.y + b.y); }
  static (Point + Number) (a, b) { return Point(a.x + b, a.y + b); }
  static (Point - Point)  (a, b) { return Point(a.x - b.x, a.y - b.y); }
  static (Point - Number) (a, b) { return Point(a.x - b, a.y - b); }
  static (Point * Number) (a, b) { return Point(a.x * b, a.y * b); }
  static (Point / Number) (a, b) { return Point(a.x / b, a.y / b); }

  static (- Point) (a) { return Point(-a.x, -b.x); }
  static (~ Point) (a) { return Point(~a.x, ~b.x); }
}

Semantics

Structs

A struct is a declaration for a data structure with value semantics. This means:

  • A struct value consists of a two pieces of information at runtime:
    • A value consisting of a contiguous chunk of memory encapsulating all of the data declared by the struct value's struct declaration.
    • A type which is a reference to the struct declaration that was used to allocate the struct value.
    • NOTE: This is analogous to the behavior of a value such as 0, which includes both its value (0) and its type (Number).
  • A struct value is copied on assignment, when passed as the argument to a function, or when passed as the expression to a return, throw, yield, or await.
  • A struct value is either mutable (if declared using struct), or immutable (if declared using const struct).
    • A struct value that is immutable cannot be modified. Attempting to mutate such a value will result in an error in strict-mode contexts.
    • A struct value this is mutable can be modified. Such modifications change the underlying memory of the struct, but do not affect copies of the struct.
  • Calling ToObject on a struct value is similar to what happens for other primitive values, in that a new ECMAScript Object is allocated whose [[Prototype]] slot points to the prototype property of the struct's constructor function, and whose [[StructData]] internal slot is set to the struct value.

Examples

struct Mutable {
  // ...
}
const struct Immutable {
  // ...
}

Fields

A struct consists of zero or more fields which define the structure, size, and organization of the underlying memory allocated for a struct value. As the memory allocated for a struct value must be contiguous, the type and size for each field generally must be known ahead of time and as such must be included as part of the struct's declaration.

A field may be declared using IdentifierName, NumberLiteral, StringLiteral, ComputedPropertyName, or PrivateIdentifier. Similar to class declarations, a PrivateIdentifier is lexically scoped to the body of the struct declaration.

A field may have an optional initializer. A field without an initializer will be initialized using a default value derived from the field's declared type.

Examples

struct Point {
  x: i32;
  y: i32;
  // ...
}

const struct Decimal {
  #sign: i8;
  #exponent: i32;
  #coefficientLength: i32;
  #coefficient: i32[#coefficientLength];
  // ...
}

Field Types

A field's field type is mandatory and must be specified following the field's name, separated by a colon (:). A field type may consist of one of the following:

  • A built-in reserved primitive type:
    • i8 - A one-byte signed integer.
    • i16 - A two-byte signed integer.
    • i32 - A four-byte signed integer.
    • i64 - An eight-byte signed integer.
    • u8 - A one-byte unsigned integer.
    • u16 - A two-byte unsigned integer.
    • u32 - A four-byte unsigned integer.
    • u64 - An eight-byte unsigned integer.
    • f32 - A four-byte floating point number.
    • f64 - An eight-byte floating point number.
    • box - A memory-managed reference to an ECMAScript language value whose size is host-dependent.
  • An IdentifierReference that evaluates to the constructor from a struct declaration (i.e., Point, etc.).

In addition, the field type may be suffixed by an array length indicator using one of the following forms:

  • A fixed-size array, such as i32[8] (in this case indicating an Int32Array of length 8).
  • A dependent-size array, such as i32[length] (in this case indicating an Int32Array whose length is derived from the struct value's length field.).
    • NOTE: In a mutable struct, changing length would resize the TypedArray, possibly causing data loss.
  • A flexible-size array, such as i32[], which may only occur as the last field in a struct.

Constructors

A struct declaration's [[Construct]] slot is overloaded, such that every struct's constructor can always be called with the following arguments:

  • (typedArray: TypedArray) - Allocates a struct value from a TypedArray.
  • (buffer: ArrayBuffer | SharedArrayBuffer, byteOffset?: number) - Allocates a struct value from an ArraBuffer or SharedArrayBuffer.

If neither of these overloads conditions are met, construction of the struct falls to either its declared constructor, or a default constructor. The default constructor for a struct consists of a parameter for each field, in declaration order. Each parameter can be considered to have an initializer consistent with the field's initializer.

Examples

struct Point {
  x: i32;
  y: i32;
}
const p1 = Point();
console.log(p1.x, p1.y); // 0 0
const p2 = Point(10);
console.log(p2.x, p2.y); // 10 0
const p3 = Point(10, 20);
console.log(p3.x, p3.y); // 10 20

Methods/Accessors

A struct may declare methods and accessors which are stored on the prototype property of the struct's constructor function. These behave similar to prototype members for Number, Boolean, etc.

Examples

struct Point {
  /* ... */
  offset(dx, dy) { return Point(this.x + dx, this.y + dy); }
  toString() { return `${this.x},${this.y}`; }
  /* ... */
}

Operator Overloading

A struct declaration supports syntactic operator overloading, allowing you to specify how a limited subset of ECMAScript binary and unary operators interact with struct values.

An operator method is a static method of the struct that specifies both the operator and the valid operator types for each operand:

  • ( Type1 BinaryOperator Type2 ) - Indicates a binary operation between Type1 (on the left) and Type2 on the right, i.e. (Point + Point). At least one of the two types must refer to the current struct.
  • ( UnaryOperator Type?) - Indicates a unary operation on Type, which must refer to the current struct.
  • NOTE: For convenience, the Type may be elided.

An operator type must be an IdentifierReference pointing to the one of the following:

  • The name of a struct declaration.
  • One of a limited set of built-in primitive constructors:
  • String - for string values.
  • Symbol - for symbol values.
  • Number - for number values.
  • BigInteger - for bigint values.
  • Boolean - for boolean values.
  • Object - for everything else.

Examples

struct Point {
  // binary operator overloading
  static (Point + Point)  (a, b) { return Point(a.x + b.x, a.y + b.y); }
  static (Point + Number) (a, b) { return Point(a.x + b, a.y + b); }
  static (Point - Point)  (a, b) { return Point(a.x - b.x, a.y - b.y); }
  static (Point - Number) (a, b) { return Point(a.x - b, a.y - b); }
  static (Point * Number) (a, b) { return Point(a.x * b, a.y * b); }
  static (Point / Number) (a, b) { return Point(a.x / b, a.y / b); }
  
  // unary operator overloading
  static (- Point) (a) { return Point(-a.x, -b.x); }
  static (~ Point) (a) { return Point(~a.x, ~b.x); }
}

Future Additions

The following are several possible future additions being considered for this or a follow-on proposal:

  • Controlling memory pack behavior using an @pack decorator.
  • Controlling field offset using an @fieldOffset decorator.

Examples

TODO: Provide examples of the proposal.

API

Every struct constructor has the following members:

  • SIZE - The minimum number of bytes required to allocate an instance of the struct.
  • Array - A TypedArray-like constructor whose elements are based on the struct.

Every struct declaration has a prototype that includes the following members:

  • buffer - The ArrayBuffer backing the struct value.
  • byteOffset - The offset, in bytes, from the start of buffer at which this struct value starts.
  • with(attrs) - A method that returns a copy of the struct value with its fields values changed based on the own properties of attrs (e.g. Point().with({ x: 10 }) === x).

Grammar

TODO: Provide the grammar for the proposal. Please use grammarkdown syntax in fenced code blocks as grammarkdown is the grammar format used by ecmarkup.

References

TODO: Provide links to other specifications, etc.

Prior Discussion

TODO: Provide links to prior discussion topics on https://esdiscuss.org.

TODO

The following is a high-level list of tasks to progress through each stage of the TC39 proposal process:

Stage 1 Entrance Criteria

  • Identified a "champion" who will advance the addition.
  • Prose outlining the problem or need and the general shape of a solution.
  • Illustrative examples of usage.
  • High-level API.

Stage 2 Entrance Criteria

Stage 3 Entrance Criteria

Stage 4 Entrance Criteria

  • Test262 acceptance tests have been written for mainline usage scenarios and merged.
  • Two compatible implementations which pass the acceptance tests: [1], [2].
  • A pull request has been sent to tc39/ecma262 with the integrated spec text.
  • The ECMAScript editor has signed off on the pull request.

About

Value Types (i.e., 'struct') for ECMAScript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published