Most of the type information are lost when the C0 source code is compiled into the C0 bytecode. However, to perform visualization and show the value of local variable, we must know the type information of variables such that we can interpret the byte sequence accordingly.
Luckily, not all information are wiped away during the compilation. The .bc0 file contains a series of comments, which reveals the source or intention of a specific operation. The calling of native functions can also provide us with type information (e.g. readline must return a string type).
Therefore, we developed a Type Inference system along side the C0Value to collect all the traces of type information and propagate the type constraint as C0VM executes.
C0Type Definition
Defined in /src/types/c0types.d.ts, we have C0Type<T extends C0TypeClass> defined as:
typeC0Type<TextendsC0TypeClass>=TextendsC0TypeClass.value?{type:T,value:C0ValueTypes}:Textends (C0TypeClass.ptr) ?{type:T,kind:"arr"|"ptr",value:C0Type<C0TypeClass>,}|{type:T,kind:"struct",value:string,// The type name of structoffset:number// Offset from the start of struct}:Textends (C0TypeClass.string) ?{type:T,value:"string"}:Textends (C0TypeClass.unknown) ?{type:T}:never;
C0TypeClass
Unlike in C, where a variable is either on stack or heap, in C0 language, only primitive types and pointers are stored on stack. All aggregate type like struct, array must be stored on heap (a.k.a. "allocated memory space").
Therefore, we classify all C0Types into three classes:
value - All primitive types
ptr - All the pointers, and array (and structures)
string - This is a special case. string is always stored on the heap, however, dereferencing a string type is not allowed in C0 language. Therefore, it is a "un-dereferenceable pointer" and we decide to put it into a separate class alone.
unknown - when the type information is unknown, we will mark it honestly as <unknown> type, which acts like the any type in TypeScript and is accepted by all functions without condition.
A C0Type is defined in a nested way. For instance, a type of string[] will be represented by
Conversion between Type and String
The function defined in ./types/c0type_utility.ts will convert C0Type to string and string to C0Type.
Type Information Source
The type information comes from four main sources:
bipush(T) -> C0Value<C0TypeClass.value>: T
newarray(T, int | unknown) -> C0Value<C0TypeClass.ptr>: T[]
alloc(T) -> C0Value<C0TypeClass.ptr>: *T
add(int | unknown, int | unknown) -> C0Value<C0TypeClass.value>: int
Other arithmetic functions will have similar effect