see also ootVm.txt; that file is older and needs to be integrated into the list in the following section
---
so i think some stuff that OVM should implement is:
- tail calls
- management of activation frames/stack frames (in some way) (e.g. save them on the heap when they need to escape for closures)
- so do we introduce the confining stack abstraction here? i think so but am not sure
- "a 'closure' instruction which handles all of the issues related to nested lexical scoping, and the management of activation frames" or something
- serialization/pickling (see SEAM and their graph store (SEAM Abstract Store) for purposes of GC and pickling; for each bit of code they store both "Alice Abstract Code (so that it can be pickled), and also as compiled code (either compiled to bytecode or to native code). Compiled code is represented as binary 'chunk' nodes in the SEAM Abstract Store; since these are opaque to SEAM, the garbage collector can't tell which other nodes they reference, therefore binary code is wrapped by a pair node which contains (points to) both a binary chunk node and also to an "immediate environment" which is a node holding references to other nodes that are referred to by the binary code. Binary code is position-independent in anticipation of being moved around by the garbage collector.")
- note: this layer can't by itself pickle functions, although it offers facilities for other layers to do so: because that requires some sort of programming language representation -- however, it can be extended to custom node types, so the HLL can define some sort of bytecode or AST representation, and the OVM backend/platform can define native code blobs; so, assuming that the HLL did that, functions can be pickled
- note: one of the important functions here is to serialize the (probably cyclic) graph of pointers in stuff in memory
- GC/memory management, read/write barriers
- ownership, e.g. distinction b/t 'move' and 'copy'
- aliases, value types vs reference types ?
- finalizers, 'resources' (in the SEAM sense of wrapping of external objects that cannot be fully reified inside the VM's object graph)
- register assignment (on the backend)
- arrays, aggregates, dicts, linked lists/S-expressions
- and interop with native data structures
- something like futures (see SEAM transients)
- concurrency spawning, synchronization and communication
- see L4
- see Golang (channels and Goroutines)
- see Erlang
- scheduler (note: interacts with I/O because knows not to reschedule a thread waiting on I/O until the I/O completes; also must support nonblocking I/O)
- see L4
- see Python event loops
- since the HLL implementation on the layer above is trusted, we can use cooperative multitasking; the HLL must implement pre-emption if desired
- bounds-checking
- capabilities/sandboxing
- however, the HLL implementation on the layer above is trusted; this is a service to make it easy for the HLL to implement capabilities, not a sandbox of the HLL implementation itself; does this mean we have an 'ambient authority/ring 0' notion so the HLL can turn off bounds-checking and debug secrets and the like?
- guaranteed private methods and fields in OOP objects
- seal/unseal
- inability to create a reference unless you are given it (e.g. cannot cast an integer to a reference)
- virtualization
- calling conventions
- interop; glue with calling to/from platform, and with platform globals and other stuff
- do we need to support any OOP stuff?
- polymorphism? parameteric or adhoc?
- expanded set of primitives (e.g. map, reduce); see ootAssemblyOps*
- first class functions? suspended computations (is this different from futures)?
- package management/binary module stuff
- dynamic loading/importing/linking/hotpatching of modules (mb call them 'components')
- runtime
- parsing and/or regexps?
- direct compilation possible even to some platforms that Boot can only be interpreted on due to its use of unrestricted indirect jumps to implement a call stack (provided that these platforms provide enough flexibility in terms of stuff like tail calls, first-class continuations, closures, lookup tables, activation records on the stack, etc to do the sort of control flow that we need)
- i guess it has to have structured control flow constructs so that it can support transpilation to native platforms. Should look at Haxe ( https://community.haxe.org/t/how-to-implement-new-haxe-target/1599/4 ).
- copy-on-write
- object model
- laziness?
- promises
- distributed message-passing/mailboxes/calls and 'eventual send'
- channels
todo should also read more about the OOP parts of JVM and CIL. todo should also read about Cmm/C-- runtime support todo update Oot todos
as you can see, the purpose of OVM is coming into focus:
- services e.g. GC that i think are annoying/administrative rather than 'cool semantics'
- note; these services should be able to be overridden by their platform-native equivalents (e.g. in Python or Java, use Python's or Java's GC if possible). Note that this means that an Oot program can't depend on their exact semantics, since this will vary with platform
- code generation stuff that i think is annoying (eg register allocation)
- primitives
- maybe some optimization?
- interop
but everything should be not very dynamic/metaprogrammable/dynamically typed (remember the lesson from PyPy?), so this is different from Oot Core.
---
Instruction format (128-bit):
1 x 16-bit opcode 3 x (16-bit operand + 8-bit addr mode) 1 x (32-bit operand + 8-bit addr mode)
16 bytes
Note that there is no space for encoding length format bits here -- UNLESS you reduced the opcode by 5 bits to 11 bits. Which isn't crazy. So maybe:
5 encoding length format bits 1 x 11-bit opcode 3 x (16-bit operand + 8-bit addr mode) 1 x (32-bit operand + 8-bit addr mode)
16 bytes
We could also have a 64-bit encoding format:
4 encoding length format bits + 2 RESERVED bits + 10-bit opcode + 4 x (8-bit operand + 4-bit addr mode)
---
i dunno man, this seems like a lot of work to implement in assembly language.
also, what about the idea of incremental implementation? how is the porter going to be able to just implement the bare VM and use existing implementations of most of the opcodes?
i guess some of these things could be compile-time macros (eg hash tables).
but i feel like we really have a couple of levels here.
maybe some/many of these things would be 'standard library functions' at the OVM level (eg hash tables).
hmm, that makes a lot more sense to me. So we would specify a smaller core VM, which has to actually be implemented, and then a large standard library. And then porters would have to implement the VM, and then for better interoperability and efficiency on a given platform they could go ahead and incrementally override parts of the standard library with platform-specific stuff.
another issue is static typing. There's a tension here:
- if this is to be a language designed for IMPLEMENTING another language, like PyPy?