microvium
Version:
A compact, embeddable scripting engine for microcontrollers for executing small scripts written in a subset of JavaScript.
342 lines (341 loc) • 14 kB
TypeScript
export declare type UInt4 = number;
export declare type UInt8 = number;
export declare type UInt7 = number;
export declare type UInt12 = number;
export declare type UInt14 = number;
export declare type UInt16 = number;
export declare type UInt32 = number;
export declare type SInt4 = number;
export declare type SInt8 = number;
export declare type SInt12 = number;
export declare type SInt14 = number;
export declare type SInt16 = number;
export declare type SInt32 = number;
export declare const UInt4: (n: UInt4) => UInt4;
export declare const UInt7: (n: UInt7) => UInt8;
export declare const UInt8: (n: UInt8) => UInt8;
export declare const UInt12: (n: UInt12) => UInt12;
export declare const UInt14: (n: UInt14) => UInt14;
export declare const UInt16: (n: UInt16) => UInt16;
export declare const UInt32: (n: UInt32) => UInt32;
export declare const SInt8: (n: SInt8) => SInt8;
export declare const SInt14: (n: SInt14) => SInt14;
export declare const SInt16: (n: SInt16) => SInt16;
export declare const SInt32: (n: SInt32) => SInt32;
export declare type mvm_Value = UInt16;
export declare type vm_Reference = mvm_Value;
export declare type vm_VMExportID = UInt16;
export declare type vm_HostFunctionID = UInt16;
export declare enum mvm_TeError {
MVM_E_SUCCESS = 0,
MVM_E_UNEXPECTED = 1,
MVM_E_MALLOC_FAIL = 2,
MVM_E_ALLOCATION_TOO_LARGE = 3,
MVM_E_INVALID_ADDRESS = 4,
MVM_E_COPY_ACROSS_BUCKET_BOUNDARY = 5,
MVM_E_FUNCTION_NOT_FOUND = 6,
MVM_E_INVALID_HANDLE = 7,
MVM_E_STACK_OVERFLOW = 8,
MVM_E_UNRESOLVED_IMPORT = 9,
MVM_E_ATTEMPT_TO_WRITE_TO_ROM = 10,
MVM_E_INVALID_ARGUMENTS = 11,
MVM_E_TYPE_ERROR = 12,
MVM_E_TARGET_NOT_CALLABLE = 13,
MVM_E_HOST_ERROR = 14,
MVM_E_NOT_IMPLEMENTED = 15,
MVM_E_HOST_RETURNED_INVALID_VALUE = 16,
MVM_E_ASSERTION_FAILED = 17,
MVM_E_INVALID_BYTECODE = 18,
MVM_E_UNRESOLVED_EXPORT = 19,
MVM_E_RANGE_ERROR = 20,
MVM_E_DETACHED_EPHEMERAL = 21,
MVM_E_TARGET_IS_NOT_A_VM_FUNCTION = 22,
MVM_E_FLOAT64 = 23,
MVM_E_NAN = 24,
MVM_E_NEG_ZERO = 25,
MVM_E_OPERATION_REQUIRES_FLOAT_SUPPORT = 26,
MVM_E_BYTECODE_CRC_FAIL = 27,
MVM_E_BYTECODE_REQUIRES_FLOAT_SUPPORT = 28,
MVM_E_PROTO_IS_READONLY = 29,
MVM_E_SNAPSHOT_TOO_LARGE = 30,
MVM_E_MALLOC_MUST_RETURN_POINTER_TO_EVEN_BOUNDARY = 31,
MVM_E_ARRAY_TOO_LONG = 32,
MVM_E_OUT_OF_MEMORY = 33,
MVM_E_TOO_MANY_ARGUMENTS = 34,
MVM_E_REQUIRES_LATER_ENGINE = 35,
MVM_E_PORT_FILE_VERSION_MISMATCH = 36,
MVM_E_PORT_FILE_MACRO_TEST_FAILURE = 37,
MVM_E_EXPECTED_POINTER_SIZE_TO_BE_16_BIT = 38,
MVM_E_EXPECTED_POINTER_SIZE_NOT_TO_BE_16_BIT = 39,
MVM_E_TYPE_ERROR_TARGET_IS_NOT_CALLABLE = 40,
MVM_E_TDZ_ERROR = 41,
MVM_E_MALLOC_NOT_WITHIN_RAM_PAGE = 42,
MVM_E_INVALID_ARRAY_INDEX = 43,
MVM_E_UNCAUGHT_EXCEPTION = 44,
MVM_E_FATAL_ERROR_MUST_KILL_VM = 45,
MVM_E_OBJECT_KEYS_ON_NON_OBJECT = 46,
MVM_E_INVALID_UINT8_ARRAY_LENGTH = 47,
MVM_E_CAN_ONLY_ASSIGN_BYTES_TO_UINT8_ARRAY = 48,
MVM_E_WRONG_BYTECODE_VERSION = 49,
MVM_E_USING_NEW_ON_NON_CLASS = 50,
MVM_E_INSTRUCTION_COUNT_REACHED = 51,
MVM_E_REQUIRES_ACTIVE_VM = 52,
MVM_E_ASYNC_START_ERROR = 53,
MVM_E_ASYNC_WITHOUT_AWAIT = 54,
MVM_E_TYPE_ERROR_AWAIT_NON_PROMISE = 55,
MVM_E_HEAP_CORRUPT = 56,
MVM_E_CLASS_PROTOTYPE_MUST_BE_NULL_OR_OBJECT = 57
}
/**
* Type code indicating the type of data.
*
* This enumeration is divided into reference types (TC_REF_) and value types
* (TC_VAL_). Reference type codes are used on allocations, whereas value type
* codes are never used on allocations. The space for the type code in the
* allocation header is 4 bits, so there are up to 16 reference types and these
* must be the first 16 types in the enumeration.
*
* The reference type range is subdivided into containers or non-containers. The
* GC uses this distinction to decide whether the body of the allocation should
* be interpreted as `Value`s (i.e. may contain pointers). To minimize the code,
* either ALL words in a container are `Value`s, or none.
*
* Value types are for the values that can be represented within the 16-bit
* mvm_Value without interpreting it as a pointer.
*/
export declare enum TeTypeCode {
TC_REF_TOMBSTONE = 0,
TC_REF_INT32 = 1,
TC_REF_FLOAT64 = 2,
/**
* UTF8-encoded string that may or may not be unique.
*
* Note: If a TC_REF_STRING is in bytecode, it is because it encodes a value
* that is illegal as a property index in Microvium (i.e. it encodes an
* integer).
*/
TC_REF_STRING = 3,
/**
* TC_REF_INTERNED_STRING
*
* A string whose address uniquely identifies its contents, and does not
* encode an integer in the range 0 to 0x1FFF.
*
* To keep property lookup efficient, Microvium requires that strings used as
* property keys can be compared using pointer equality. This requires that
* there is only one instance of each of those strings (see
* https://en.wikipedia.org/wiki/String_interning).
*
* A string with the type code TC_REF_INTERNED_STRING means that it exists in
* one of the interning tables (either the one in ROM or the one in RAM). Not
* all strings are interned, because it would be expensive if every string
* concatenation resulted in a search of the intern table and possibly a new
* entry (imagine if every JSON string landed up in the table!).
*
* In practice we do this:
*
* - All valid non-index property keys in ROM are interned. If a string is in
* ROM but it is not interned, the engine can conclude that it is not a
* valid property key or it is an index.
* - Strings constructed in RAM are only interned when they're used to access
* properties.
*/
TC_REF_INTERNED_STRING = 4,
TC_REF_FUNCTION = 5,
TC_REF_HOST_FUNC = 6,
TC_REF_UINT8_ARRAY = 7,
TC_REF_SYMBOL = 8,
TC_REF_DIVIDER_CONTAINER_TYPES = 9,
TC_REF_CLASS = 9,
TC_REF_VIRTUAL = 10,
TC_REF_RESERVED_1 = 11,
TC_REF_PROPERTY_LIST = 12,
TC_REF_ARRAY = 13,
TC_REF_FIXED_LENGTH_ARRAY = 14,
TC_REF_CLOSURE = 15,
TC_VAL_INT14 = 16,
TC_VAL_UNDEFINED = 17,
TC_VAL_NULL = 18,
TC_VAL_TRUE = 19,
TC_VAL_FALSE = 20,
TC_VAL_NAN = 21,
TC_VAL_NEG_ZERO = 22,
TC_VAL_DELETED = 23,
TC_VAL_STR_LENGTH = 24,
TC_VAL_STR_PROTO = 25,
/**
* TC_VAL_NO_OP_FUNC
*
* Represents a function that does nothing and returns undefined.
*
* This is required by async-await for the case where you void-call an async
* function and it needs to synthesize a dummy callback that does nothing,
* particularly for a host async function to call back.
*/
TC_VAL_NO_OP_FUNC = 26,
TC_END = 27
}
export declare enum mvm_TeType {
VM_T_UNDEFINED = 0,
VM_T_NULL = 1,
VM_T_BOOLEAN = 2,
VM_T_NUMBER = 3,
VM_T_STRING = 4,
VM_T_FUNCTION = 5,
VM_T_OBJECT = 6,
VM_T_ARRAY = 7,
VM_T_UINT8_ARRAY = 8,
VM_T_CLASS = 9,
VM_T_SYMBOL = 10,
VM_T_BIG_INT = 11,
VM_T_END = 12
}
export declare enum mvm_TeBuiltins {
BIN_INTERNED_STRINGS = 0,
BIN_ARRAY_PROTO = 1,
BIN_STR_PROTOTYPE = 2,
BIN_ASYNC_CONTINUE = 3,
BIN_ASYNC_CATCH_BLOCK = 4,
BIN_ASYNC_HOST_CALLBACK = 5,
BIN_PROMISE_PROTOTYPE = 6,
BIN_BUILTIN_COUNT = 7
}
export declare enum vm_TeWellKnownValues {
VM_VALUE_UNDEFINED = 1,
VM_VALUE_NULL = 5,
VM_VALUE_TRUE = 9,
VM_VALUE_FALSE = 13,
VM_VALUE_NAN = 17,
VM_VALUE_NEG_ZERO = 21,
VM_VALUE_DELETED = 25,
VM_VALUE_STR_LENGTH = 29,
VM_VALUE_STR_PROTO = 33,
VM_VALUE_NO_OP_FUNC = 37,
VM_VALUE_WELLKNOWN_END = 38
}
export declare function isUInt4(value: number): boolean;
export declare function isUInt7(value: number): boolean;
export declare function isSInt8(value: number): boolean;
export declare function isUInt8(value: number): boolean;
export declare function isUInt12(value: number): boolean;
export declare function isSInt14(value: number): boolean;
export declare function isUInt14(value: number): boolean;
export declare function isUInt16(value: number): boolean;
export declare function isSInt16(value: number): boolean;
export declare function isSInt32(value: number): boolean;
export declare function isUInt32(value: number): boolean;
export declare enum mvm_TeBytecodeSection {
/**
* Import Table
*
* List of host function IDs (vm_TsImportTableEntry) which are called by the
* VM. References from the VM to host functions are represented as indexes
* into this table. These IDs are resolved to their corresponding host
* function pointers when a VM is restored.
*/
BCS_IMPORT_TABLE = 0,
/**
* A list of immutable `vm_TsExportTableEntry` that the VM exports, mapping
* export IDs to their corresponding VM Value. Mostly these values will just
* be function pointers.
*/
BCS_EXPORT_TABLE = 1,
/**
* Short Call Table. Table of vm_TsShortCallTableEntry.
*
* To make the representation of function calls in IL more compact, up to 256
* of the most frequent function calls are listed in this table, including the
* function target and the argument count.
*
* See `LBL_CALL_SHORT`
*/
BCS_SHORT_CALL_TABLE = 2,
/**
* Builtins
*
* See `mvm_TeBuiltins`
*
* Table of `Value`s that need to be directly identifiable by the engine, such
* as the Array prototype.
*
* These are not copied into RAM, they are just constant values like the
* exports, but like other values in ROM they are permitted to hold mutable
* values by pointing (as BytecodeMappedPtr) to the corresponding global
* variable slot.
*
* Note: at one point, I had these as single-byte offsets into the global
* variable space, but this made the assumption that all accessible builtins
* are also mutable, which is probably not true. The new design makes the
* opposite assumption: most builtins will be immutable at runtime (e.g.
* nobody changes the array prototype), so they can be stored in ROM and
* referenced by immutable Value pointers, making them usable but not
* consuming RAM at all. It's the exception rather than the rule that some of
* these may be mutable and require indirection through the global slot table.
*/
BCS_BUILTINS = 3,
/**
* Interned Strings Table
*
* To keep property lookup efficient, Microvium requires that strings used as
* property keys can be compared using pointer equality. This requires that
* there is only one instance of each string (see
* https://en.wikipedia.org/wiki/String_interning). This table is the
* alphabetical listing of all the strings in ROM (or at least, all those
* which are valid property keys). See also TC_REF_INTERNED_STRING.
*
* There may be two string tables: one in ROM and one in RAM. The latter is
* required in general if the program might use arbitrarily-computed strings
* as property keys. For efficiency, the ROM string table is contiguous and
* sorted, to allow for binary searching, while the RAM string table is a
* linked list for efficiency in appending (expected to be used only
* occasionally).
*/
BCS_STRING_TABLE = 4,
/**
* Functions and other immutable data structures.
*
* While the whole bytecode is essentially "ROM", only this ROM section
* contains addressable allocations.
*/
BCS_ROM = 5,
/**
* Globals
*
* One `Value` entry for the initial value of each global variable. The number
* of global variables is determined by the size of this section.
*
* This section will be copied into RAM at startup (restore).
*
* Note: the global slots are used both for global variables and for "handles"
* (these are different to the user-defined handles for referencing VM objects
* from user space). Handles allow ROM allocations to reference RAM
* allocations, even though the ROM can't be updated when the RAM allocation
* moves during a GC collection. A handle is a slot in the "globals" space,
* where the slot itself is pointed to by a ROM value and it points to the
* corresponding RAM value. During a GC cycle, the RAM value may move and the
* handle slot is updated, but the handle slot itself doesn't move. See
* `offsetToDynamicPtr` in `encode-snapshot.ts`.
*
* The handles appear as the *last* global slots, and will generally not be
* referenced by `LOAD_GLOBAL` instructions.
*
* WARNING: the globals section is the last section before the heap, so no ROM
* pointer should point after the globals section. Some functions (e.g.
* vm_getHandleTargetOrNull) assume this to be true.
*/
BCS_GLOBALS = 6,
/**
* Heap Section: heap allocations.
*
* This section is copied into RAM when the VM is restored. It becomes the
* initial value of the GC heap. It contains allocations that are mutable
* (like the DATA section) but also subject to garbage collection.
*
* Note: the heap must be at the end, because it is the only part that changes
* size from one snapshot to the next. There is code that depends on this
* being the last section because the size of this section is computed as
* running to the end of the bytecode image.
*/
BCS_HEAP = 7,
BCS_SECTION_COUNT = 8
}