/* ----------------------------------------------------------------------------- Copyright 2019-2023 Kevin P. Barry Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------------------------------------------------------------- */ // Author: Kevin P. Barry [ta0kira@gmail.com] // Built-in boolean type. // // Literals are true and false. // // Notes: // - You do not need () to make a function call on a literal; something like // true.asInt() is totally fine. // - Values are unboxed when storing in variables. concrete Bool { immutable refines AsBool refines AsInt refines AsFloat refines Duplicate refines Formatted refines Hashed defines Default defines Equals defines LessThan } // Built-in 8-bit character type. // // Literals: // - Printable: 'a', '0', etc. // - Escapes: '\n', '\r', etc. ('\0' must be octal '\000', however) // - Hex: '\xAB' (always 2 digits) // - Oct: '\012' (always 3 digits) // // Notes: // - You do not need () to make a function call on a literal; something like // 'a'.asInt() is totally fine. // - When converting to Int with asInt(), the value will always be unsigned, // i.e., beween 0-255. ASCII characters will be in the 0-127 range. // - Values are unboxed when storing in variables. concrete Char { immutable refines AsBool refines AsChar refines AsInt refines AsFloat refines Duplicate refines Formatted refines Hashed defines Bounded defines Default defines Equals defines LessThan } // Built-in double-precision floating point. // // Literals: // - . required, with at least one digit on either side, e.g., 0.1 // - Scientific notation: 0.1E-10, etc. // - Hex: \xABC.DEF, etc. // - Octal: \o777.266, etc. // - Binary: \b011.011, etc. // // Notes: // - You must use () to make a function call on a literal, e.g, (1.1).asInt(). // - Values are unboxed when storing in variables. concrete Float { immutable refines AsBool refines AsInt refines AsFloat refines Duplicate refines Formatted refines Hashed defines Default defines Equals defines LessThan } // Built-in 64-bit signed integer. // // Literals: // - Decimal: 1234, -1234, etc. // - Hex: \xABCD, etc. // - Octal: \o7772, etc. // - Binary: \b0110, etc. // // Notes: // - Overflow will cause a compilation error. // - Hex, oct, and binary escapes can go up to 2^64-1 to allow use of all 64 // bits, but they will still be used as signed values. // - You must use () to make a function call on a literal, e.g, (100).asFloat(). // - When converting to Char with asChar(), the value will always be treated as // unsigned, i.e., beween 0-255 mod 256. // - Values are unboxed when storing in variables. concrete Int { immutable refines AsBool refines AsChar refines AsInt refines AsFloat refines Duplicate refines Formatted refines Hashed defines Bounded defines Default defines Equals defines LessThan } // Built-in string of characters. (ASCII only.) // // Literals: Quote Char sequence with ". // // Notes: // - You do not need () to make a function call on a literal; something like // "abc".defaultOrder() is totally fine. concrete String { immutable refines AsBool refines DefaultOrder refines Duplicate refines Formatted refines Hashed refines ReadAt refines SubSequence defines Default defines Equals defines LessThan // Create a new String as an immutable copy of a CharBuffer. // // Notes: // - Changing the data in the CharBuffer after copying will not result in // modifications to the String returned here. // - Data will be copied verbatim, even if some characters are null. @type fromCharBuffer (CharBuffer) -> (String) // Get a builder to create a string using concatenation. // // Example: // // String.builder().append("foo").append("bar").build() @type builder () -> ([Append & Build]) } // Built-in fixed-size buffer of byte data. // // Literals: None. concrete CharBuffer { refines ReadAt refines WriteAt // Create a new buffer with a fixed size. // // Notes: // - The implementation does not guarantee that the values will be zeroed. @type new (Int) -> (CharBuffer) // Resize the buffer to the specified size. // // Notes: // - The implementation does not guarantee that the values will be zeroed. // Specifically, resizing down and then back up again could either preserve // or overwrite any of the data. @value resize (Int) -> (CharBuffer) } // A raw pointer type for use in C++ extensions. // // Literals: None. // // Notes: // - #x is mostly irrelevant. It is only intended for differentiating between // values with incompatible types. // - This is category is only meant for passing C++ data between extensions when // it would otherwise require marshaling, which is why it has no functions. // - Values are unboxed when storing in variables. concrete Pointer<#x> { immutable } // An identifier for a value instance. // // Literals: None. // // Notes: // - Get an Identifier<#x> from optional #x value with instance(value). // - Also supports comparisons, e.g., <, ==. // - Values are unboxed when storing in variables. // - Identifiers will be unique for different concrete values if: // - Both underlying concrete types are unboxed, which is the case with all // custom concrete types. // - Both values existed at the same time at some point. concrete Identifier<|#x> { immutable refines Formatted refines Hashed defines Equals> defines LessThan> } // Convertible to Bool. @value interface AsBool { // Convert the value to Bool. asBool () -> (Bool) } // Convertible to Char. @value interface AsChar { // Convert the value to Char. asChar () -> (Char) } // Convertible to Float. @value interface AsFloat { // Convert the value to Float. asFloat () -> (Float) } // Convertible to Int. @value interface AsInt { // Convert the value to Int. asInt () -> (Int) } // Formattable as a String. @value interface Formatted { // Format the value as a String. (Does not need to be reversible.) formatted () -> (String) } // Supports appending. // // Params: // - #x: The value type to append. @value interface Append<#x|> { // Append a value and return self. append (#x) -> (#self) } // Supports building a value from the current state. // // Params: // - #x: The value type to build. @value interface Build<|#x> { // Build and return a value from the current state. build () -> (#x) } // Ordered data, primarily used for the traverse built-in. // // Example: // // // defaultOrder() returns optional Order for traverse to use. // traverse ("letters".defaultOrder() -> Char c) { // // code that uses Char c // } @value interface Order<|#x> { // Returns an updated instance, or empty if the end was reached. // // Notes: // - This can return either a mutated self or a new copy. The caller should // assume that next() will mutate the instance. // - This should not generally be used directly; use the traverse built-in. next () -> (optional #self) // Returns the value at the current position. // // Notes: // - If the value is discarded in traverse with -> _ then the call to get will // be skipped; therefore, get should not have side-effects. // - This should not generally be used directly; use the traverse built-in. get () -> (#x) } // Provides a default Order for a container. // // Notes: // - The return value is primarily intended for use with the traverse built-in. // - Also see the documentation for Order and traverse. @value interface DefaultOrder<|#x> { // Returns the default Order for the container. defaultOrder () -> (optional Order<#x>) } // Can be hashed. // // Notes: // - This interface is primarily intended for use with containers. // - The returned hash does not need to match across different executions of the // same program. @value interface Hashed { // Hashes the object. hashed () -> (Int) } // Contains a flexible number of values of some type. @value interface Container { // Return the number of values. size () -> (Int) } // Can be duplicated. @value interface Duplicate { // Creates a duplicate that can be mutated without changing the original. // // Notes: // - This does not need to be a deep copy. The only requirement is that // mutating functions can be called on the copy without counterintuitive // results. For example, if the object is a container, the duplicate could // be a copy of the structure, while still referring to the same objects. duplicate () -> (#self) } // Random-access reading from a container. // // Params: // - #x: The value type contained. @value interface ReadAt<|#x> { refines Container // Return the value at the given index. readAt (Int) -> (#x) } // Random-access writing to a container. // // Params: // - #x: The value type contained. @value interface WriteAt<#x|> { refines Container // Write the value at the given index and return self. writeAt (Int, #x) -> (#self) } // Sequence that can be subsequenced. @value interface SubSequence { refines Container // Return a copy of a subsequence. subSequence (Int, Int) -> (#self) } // The type has a default value. @type interface Default { // Return a new copy of the default value. default () -> (#self) } // The type has both min and max bounds. // // Notes: // - The implementation should return either an immutable object or a new object // for every call, so that mutations are localized. @type interface Bounded { // The min bound of the type. minBound () -> (#self) // The max bound of the type. maxBound () -> (#self) } // The type can compare values for equality. // // Params: // - #x: The value type to be compared. @type interface Equals<#x|> { // Returns true iff the two values are equal. Must be symmetric. equals (#x, #x) -> (Bool) } // The type can compare values for less-than. // // Params: // - #x: The value type to be compared. @type interface LessThan<#x|> { // Returns true iff the first value is less than the second. lessThan (#x, #x) -> (Bool) }