Skip to content

Latest commit

 

History

History
484 lines (328 loc) · 9.69 KB

File metadata and controls

484 lines (328 loc) · 9.69 KB

DeviceScript bytecode spec

TODO

  • object prototypes
  • object property lookup by string, not index
  • closures - just keep pointer to parent stack frame - in parent clear pointer variables on last use or exit
  • try/catch
  • drop seconds, use milliseconds everywhere
  • multi-program LATER

Tree-shaking

  • in ES tree shaking typically only applies to functions, not class/object methods
  • should people even use classes?

Decisions

  • utf16 vs utf8 strings - UTF8
  • null vs undefined
  • hash-consing of strings? (esp. for JSON parsing) LATER
  • call method identified by string -> eg. charCodeAt YES
  • prototype property access via string lookup?

Philosophy

  • static vs dynamic
  • use types in compilation?
  • built-in methods vs opcodes

Dynamic methods

  • obj.prop -> (objptr, intr-method-index/function-index)

  • role.packet -> (roleidx, spec-offset)

  • builtin_field(*idx, obj)

  • ascii_field(*idx, obj)

  • gen_field(field, obj)

  • call0(fn), call1(fn,arg0), call2(fn,arg0,arg1), ..., call4(...)

  • Math.max = ...; Math.clamp = ...

  • Array.prototype.subarray = ...

  • led.active.proto.foo = ... ? nope. frozen.

function foo() {
    const x = ...
    Bar.prototype.baz = function () { return this.q + x } - disallow
}
// bar.baz -> ???

Ops

Control flow

call0(func) = 2                                   // CALL func()
call1(func, v0) = 3                               // CALL func(v0)
call2(func, v0, v1) = 4                           // CALL func(v0, v1)
call3(func, v0, v1, v2) = 5                       // CALL func(v0, v1, v2)
call4(func, v0, v1, v2, v3) = 6                   // CALL func(v0, v1, v2, v3)
call5(func, v0, v1, v2, v3, v4) = 7               // CALL func(v0, v1, v2, v3, v4)
call6(func, v0, v1, v2, v3, v4, v5) = 8           // CALL func(v0, v1, v2, v3, v4, v5)
call7(func, v0, v1, v2, v3, v4, v5, v6) = 9       // CALL func(v0, v1, v2, v3, v4, v5, v6)
call8(func, v0, v1, v2, v3, v4, v5, v6, v7) = 10  // CALL func(v0, v1, v2, v3, v4, v5, v6, v7)

Short-hand versions of regular call opcode.

return(value) = 12

jmp(*jmpoffset) = 13               // JMP jmpoffset

jmp_z(*jmpoffset, x) = 14          // JMP jmpoffset IF NOT x

Jump if condition is false.

panic(error_code) = 15

Variables

store_local(*local_idx, value) = 17      // local_idx := value

store_global(*global_idx, value) = 18    // global_idx := value

store_buffer(buffer, numfmt, offset, value) = 19

load_local(*local_idx): any = 21

load_global(*global_idx): any = 22

Field access

fun index(object, idx): any = 24              // object[idx]

Read named field or sequence member (depending on type of idx).

index_set(object, index, value) = 25         // object[index] := value

Write named field or sequence member (depending on type of idx).

builtin_field(*builtin_idx, obj): any = 26  // [builtin_idx]obj

Shorthand to index(obj, static_builtin_string(builtin_idx))

ascii_field(*ascii_idx, obj): any = 27      // [ascii_idx]obj

Shorthand to index(obj, static_ascii_string(ascii_idx))

utf8_field(*utf8_idx, obj): any = 28        // [utf8_idx]obj

Shorthand to index(obj, static_utf8_string(utf8_idx))

fun math_field(*builtin_idx): any = 29      // Math.builtin_idx

fun ds_field(*builtin_idx): any = 30        // ds.builtin_idx

Objects

alloc_map() = 31

alloc_array(initial_size) = 32

alloc_buffer(size) = 33

Statics

fun static_role(*role_idx): role = 34

fun static_buffer(*buffer_idx): buffer = 35

fun static_builtin_string(*builtin_idx): string = 36

fun static_ascii_string(*ascii_idx): string = 37

fun static_utf8_string(*utf8_idx): string = 38

fun static_function(*func_idx): function = 39

fun literal(*value): number = 40

fun literal_f64(*f64_idx): number = 41

fun builtin_object(*builtin_object): number = 1

Misc

load_buffer(buffer, numfmt, offset): number = 43

ret_val: any = 44

Return value of query register, call, etc.

fun typeof(object): number = 45

Returns Object_Type enum.

fun null(): null = 46

Returns null value.

fun is_null(x): bool = 47

Check if object is exactly null.

Booleans

fun true(): bool = 48

fun false(): bool = 49

fun to_bool(x): bool = 50   // !!x

Math operations

fun nan(): number = 51

fun abs(x): number = 52

fun bit_not(x): number = 53   // ~x

fun is_nan(x): bool = 54

fun neg(x): number = 55   // -x

fun not(x): bool = 56   // !x

fun to_int(x): number = 57

Same as x | 0.

fun add(x, y): number = 58     // x + y

fun sub(x, y): number = 59     // x - y

fun mul(x, y): number = 60     // x * y

fun div(x, y): number = 61     // x / y

fun bit_and(x, y): number = 62 // x & y

fun bit_or(x, y): number = 63  // x | y

fun bit_xor(x, y): number = 64 // x ^ y

fun shift_left(x, y): number = 65      // x << y

fun shift_right(x, y): number = 66      // x >> y

fun shift_right_unsigned(x, y): number = 67      // x >>> y

fun eq(x, y): bool = 68      // x == y

fun le(x, y): bool = 69      // x <= y

fun lt(x, y): bool = 70      // x < y

fun ne(x, y): bool = 71      // x != y

To be removed (mostly)

terminate_fiber(fiber_handle) = 72

Returns nan (fiber doesn't exists) or 0 (terminated).

wait_role(role) = 73

Wait until any packet arrives from specified role.

query_reg(role, code, timeout) = 74

send_cmd(role, code) = 75

query_idx_reg(role, code, string, timeout) = 76

setup_pkt_buffer(size) = 77

set_pkt(buffer, offset) = 78

Copy given string to packet buffer at given offset. Same as blit(pkt_buffer, offset, buffer, 0, null).

now_ms: number = 79

Time since device restart in ms; time only advances when sleeping.

str0eq(buffer, offset): bool = 11

get_fiber_handle(func): fiber = 80

If func == null returns self-handle. Otherwise, returns a handle or null if fiber with given function at the bottom is not currently running.

pkt_size(): number = 81

pkt_ev_code(): number = 82

pkt_reg_get_code(): number = 20

pkt_report_code(): number = 23

pkt_command_code(): number = 16

fun pkt_buffer(): buffer = 42

Return reference to "buffer" with the packet data.

Format Constants

img_version = 0x01_00_0000
magic0 = 0x53766544 // "DevS"
magic1 = 0x9a6a7e0a
num_img_sections = 8
fix_header_size = 32
section_header_size = 8
function_header_size = 16
role_header_size = 8
ascii_header_size = 2
binary_size_align = 32
max_stack_depth = 10
direct_const_op = 0x80
direct_const_offset = 16
first_multibyte_int = 0xf8
first_non_opcode = 0x10000
first_builtin_function = 50000
max_args_short_call = 8

Enum: StrIdx

buffer = 0
builtin = 1
ascii = 2
utf8 = 3
_shift = 14

Enum: OpCall

sync = 0

Regular call. Unused.

bg = 1

Always start new fiber.

bg_max1 = 2

Start new fiber unless one is already running.

bg_max1_pend1 = 3

If fiber is already running, set a flag for it to be restarted when it finishes. Otherwise, start new fiber.

bg_max1_replace = 4

Start new fiber. If it's already running, replace it.

Enum: BytecodeFlag

num_args_mask = 0xf
is_stmt = 0x10
takes_number = 0x20
is_stateless = 0x40 // fun modifier

Enum: FunctionFlag

needs_this = 0x01

Enum: NumFmt

Size in bits is: 8 << (fmt & 0b11). Format is ["u", "i", "f", "reserved"](fmt >> 2)

U8 = 0b0000
U16 = 0b0001
U32 = 0b0010
U64 = 0b0011
I8 = 0b0100
I16 = 0b0101
I32 = 0b0110
I64 = 0b0111
F8 = 0b1000 // not supported
F16 = 0b1001 // not supported
F32 = 0b1010
F64 = 0b1011

Enum: Object_Type

null = 0

Only the null value.

number = 1

Integers, doubles, infinity, nan.

map = 2

array = 3

buffer = 4

role = 5

bool = 6

Only true and false values.

fiber = 7

function = 8

string = 9

Object_Types only used in static type info

any = 10

void = 11

Enum: BuiltIn_Object

Math = 0
Object = 1
Object_prototype = 2
Array = 3
Array_prototype = 3
Buffer = 4
Buffer_prototype = 5
String = 6
String_prototype = 7
Number = 8
Number_prototype = 9
Fiber = 10
Fiber_prototype = 11
Role = 12
Role_prototype = 13
Function = 14
Function_prototype = 15
Boolean = 16
Boolean_prototype = 17
DeviceScript = 18

Enum: BuiltIn_String

_empty = 0
MInfinity = 1 // -Infinity
DeviceScript = 2
E = 3
Infinity = 4
LN10 = 5
LN2 = 6
LOG10E = 7
LOG2E = 8
NaN = 9
PI = 10
SQRT1_2 = 11
SQRT2 = 12
abs = 13
alloc = 14
array = 15
blitAt = 16
boolean = 17
buffer = 18
cbrt = 19
ceil = 20
charCodeAt = 21
clamp = 22
exp = 23
false = 24
fillAt = 25
floor = 26
forEach = 27
function = 28
getAt = 29
idiv = 30
imul = 31
isConnected = 32
join = 33
length = 34
log = 35
log10 = 36
log2 = 37
map = 38
max = 39
min = 40
next = 41
null = 42
number = 43
onChange = 44
onConnected = 45
onDisconnected = 46
packet = 47
panic = 48
pop = 49
pow = 50
prev = 51
prototype = 52
push = 53
random = 54
randomInt = 55
read = 56
reboot = 57
round = 58
setAt = 59
setLength = 60
shift = 61
signal = 62
slice = 63
splice = 64
sqrt = 65
string = 66
subscribe = 67
toString = 68
true = 69
undefined = 70
unshift = 71
wait = 72
write = 73

sleepMs = 74
imod = 75
format = 76
insert = 77
start = 78
cloud = 79
main = 80