load help;

@[name]
daovm.architecture
@[name]

@[title]
The architecture of the Dao Virtual Machine
@[title]




@[name]
daovm.architecture.vmspace
@[name]

@[title]
VM Space
@[title]


@[name]
daovm.architecture.namespace
@[name]

@[title]
Namespace
@[title]


@[name]
daovm.architecture.class
@[name]

@[title]
Class
@[title]


@[name]
daovm.architecture.routine
@[name]

@[title]
Routine
@[title]


@[name]
daovm.architecture.process
@[name]

@[title]
VM Process
@[title]


@[name]
daovm.architecture.instruction
@[name]

@[title]
VM Instructions
@[title]

@[text]
@[code]
DVM_NOP      # no operation, the VM assumes maximum one NOP between two effective codes;
DVM_DATA     # create primitive data: A: type<=DAO_COMPLEX, B: value, C: register;
DVM_GETCL    # get local const: C = A::B; A=0; B, index of the constant;
DVM_GETCK    # get class const: C = A::B; current class, A=0; parent class: A>=1;
DVM_GETCG    # get global const: C = A::B; current namespace, A=0; loaded: A>=1;
DVM_GETVH    # get host variable from code section: C = A::B; A, outer level;
DVM_GETVS    # get static variable or captured up variable from closure;
DVM_GETVO    # get instance object variables: C = A::B; A=0;
DVM_GETVK    # get class global variables: C = A::B; A: the same as GETCK;
DVM_GETVG    # get global variables: C = A::B; A: the same as GETCG;
DVM_GETI     # GET Item(s) : C = A[B];
DVM_GETDI    # GET Item(s) : C = A[B], B is the (direct) index;
DVM_GETMI    # GET Item(s) : C = A[A+1, ..., A+B];
DVM_GETF     # GET Field : C = A.B
DVM_SETVH    # set host variable in code section: C::B = A; C, outer level;
DVM_SETVS    # set static variable or captured up variable from closure;
DVM_SETVO    # set object variables: C::B = A, C the same as A in DVM_GETVO
DVM_SETVK    # set class variables: C::B = A, C the same as A in DVM_GETVK
DVM_SETVG    # set global variables: C::B = A, C the same as A in DVM_GETVG
DVM_SETI     # SET Item(s) : C[B] = A;
DVM_SETDI    # SET Item(s) : C[B] = A, B is the (direct) index;
DVM_SETMI    # SET Item(s) : C[C+1, ..., C+B] = A;
DVM_SETF     # SET Field : C.B = A
DVM_LOAD     # put local value A as reference at C;
DVM_CAST     # convert A to C if they have different types;
DVM_MOVE     # C = A; if B==0, XXX it is compile from assignment, for typing system only
DVM_NOT      # C = ! A; not
DVM_MINUS    # C = - A; unary minus;
DVM_TILDE    # C = ~ A
DVM_SIZE     # C = % A; size operation;
DVM_ADD      # C = A + B;
DVM_SUB      # C = A - B;
DVM_MUL      # C = A * B;
DVM_DIV      # C = A / B;
DVM_MOD      # C = A % B;
DVM_POW      # C = A ** B;
DVM_AND      # C = A && B;
DVM_OR       # C = A || B;
DVM_LT       # C = A <  B;
DVM_LE       # C = A <= B;
DVM_EQ       # C = A == B;
DVM_NE       # C = A != B;
DVM_IN       # C = A in B;
DVM_BITAND   # C = A & B
DVM_BITOR    # C = A | B
DVM_BITXOR   # C = A ^ B
DVM_BITLFT   # C = A << B
DVM_BITRIT   # C = A >> B
DVM_CHECK    # check type: C = A ?= B; C = A ?< B, where A is data, B is data or type
DVM_NAMEVA   # C = A => B: name A, local constant, value B, local register
DVM_PAIR     # C = A : B; create a pair of index, as a tuple;
DVM_TUPLE    # tuple: C = ( A, A+1, ..., A+B-1 ); B>=2, items can be: name=>value
DVM_LIST     # list:  C = { A, A+1, ..., A+B-1 };
DVM_MAP      # map:   C = { A => A+1, ..., A+B-2 => A+B-1 }; if B==0, empty;
DVM_HASH     # hash:  C = { A -> A+1, ..., A+B-2 -> A+B-1 }; if B==0, empty;
DVM_VECTOR   # vector: C = [ A, A+1, ..., A+B-1 ];
DVM_MATRIX   # matrix: C=[A,..,A+c-1;..;A+c*(r-1),..,A+c*r-1]; B=rc;r,c:8-bits each.
DVM_APLIST   # arithmetic progression list: C = { A : ... : A+B-1 }, B = 2 or 3;
DVM_APVECTOR # arithmetic progression vector: C = [ A : ... : A+B-1 ], B = 2 or 3;
DVM_CURRY    # class_or_routine_name: A{ A+1, ..., A+B }
DVM_MCURRY   # object.method: A{ A+1, ..., A+B }
DVM_ROUTINE  # create a function, possibly with closure
DVM_CLASS    # C = class{}, A,A+1,..A+B: A, tuple, A+1, proto class, A+2,.. proto values
DVM_GOTO     # go to B;
DVM_SWITCH   # A: variable, B: location of default codes, C: number of cases
DVM_CASE     # A: constant of the case, B: location of the case codes, C: case mode
DVM_ITER     # create an iterator at C for A if B==0, else test an array of iterators;
DVM_TEST     # if A, go to the next one; else, goto B-th instruction;
DVM_MATH     # C = A( B ); A: sin,cos,...; B: double,complex
DVM_CALL     # function call: C = A( A+1, A+2, ..., A+B ); If B==0, no parameters;
DVM_MCALL    # method call: x.y(...), pass x as the first parameter;
DVM_RETURN   # return A,A+1,..,A+B-1; B==0: no returns; C==1: return from functional;
DVM_YIELD    # yield A, A+1,.., A+B-1; return data at C when resumed;
DVM_EVAL     # evaluate a code section: C=@@(A){}, if B==1, otherwise, C=@@{};
DVM_SECT     # code section label, parameters: A,A+1,...,A+B-1; C #explicit parameters;
DVM_JITC     # run Just-In-Time compiled Code A, and skip the next B instructions;
DVM_DEBUG    # prompt to debugging mode;
@[code]
@[text]





@[name]
daovm.architecture.bytecode
@[name]

@[title]
Bytecode Format
@[title]

@[text]


This document contains specifications of the bytecode format for Dao virtual machine.
In this bytecode format, integers are always stored in big endian.


In the following specifications or examples, each byte is represented by
two hexadecimal digits, unless it is quoted by quotation marks.


@[section]
Header Section
@[section]

The header section contains 32 bytes, which are divided as the following:
@[code]
Byte       # ESC, 0x1B;
Byte       # 0x44, namely 'D';
Byte       # 0x61, namely 'a';
Byte       # 0x6F, namely 'o';
Byte       # major version number, 0x2;
Byte       # minor version number, 0x0;
Byte       # Carriage Return (CR), 0x0D;
Byte       # Line Feed (LF), 0x0A;
Byte       # format class, 0x0 for the official one;
Byte       # size of integer type, default 0x4;
Byte[4]    # format hash (rotating hash of the ASM tags and VM opcodes);
Byte[16]   # 16 reserved bytes;
Byte       # Carriage Return (CR), 0x0D;
Byte       # Line Feed (LF), 0x0A;
@[code]

The ninth byte is for format class, where 0x0 is reserved for the official format,
and 0x1 for encrypted format (only the main section is encrypted,
see below for more information).


The four bytes for format hash serves as a signature for the format in which
the bytecode is encoded. It is the rotating hash value of a string that is
constructed from the bytecode tag indices and names, and virtual machine
opcode indices and names:
@[code]
TagIndex1:TagName1;TagIndex2:TagName2;...; OpcodeIndex1:OpcodeName1;...
@[code]
Each index is separated with its corresponding name by a colon;
and each pair of index and name is followed by a semicolon.
The substrings for bytecode tags and opcodes are seperated by a blank space.
The rotating hash is computed by
@[code]
hash = length( text );
for(byte in text) hash = ((hash<<4)^(hash>>28)^byte)&0x7fffffff;
return hash;
@[code]


@[section]
Source Path Section
@[section]

@[code]
Byte[2]    # length of the source path;
Byte[]     # source path (null-terminated);
Byte       # Carriage Return (CR), 0x0D;
Byte       # Line Feed (LF), 0x0A;
@[code]


@[section]
Main Section
@[section]

The main section is encoded as structured blocks.
Each block is divided into chunks of 9 bytes, where the first byte
always stores a tag which identifies the chunk type.
The remaining 8 bytes are used to store data.


There are the following type of chunks:
@[code]
ASM_COPY
ASM_TYPEOF
ASM_TYPEDEF
ASM_ROUTINE
ASM_CLASS
ASM_INTERFACE
ASM_ENUM
ASM_TYPE
ASM_VALUE
ASM_EVAL
ASM_BASES
ASM_DECOS
ASM_PATTERNS
ASM_CONSTS
ASM_TYPES
ASM_CODE
ASM_END
ASM_LOAD
ASM_USE
ASM_VERBATIM
ASM_CONST
ASM_STATIC
ASM_GLOBAL
ASM_VAR
ASM_DATA
ASM_DATA2
ASM_SEEK
@[code]


@[section]
Chunk Specifications:
@[section]

@[subsection]
Values:
@[subsection]

@[code]
int:
ASM_VALUE(1Byte): DAO_INTEGER(1Bytes), Zeros(7Bytes);
ASM_END(1B): Value(4B/8B), Zeros(4B/0B);


float:
ASM_VALUE(1B): DAO_FLOAT(1B), Zeros(7B);
ASM_END(1B): Value(4B), Zeros(4B);


double:
ASM_VALUE(1B): DAO_DOUBLE(1B), Zeros(7B);
ASM_END(1B): Value(8B);


complex:
ASM_VALUE(1B): DAO_COMPLEX(1B), Zeros(7B);
  ASM_DATA(1B): Real(8B);
ASM_END(1B): Imag(8B);


long:
ASM_VALUE(1B): DAO_LONG(1B), Base(1B), Sign(1B), SizeMod16(1B), Digits(4B);
  ASM_DATA(1B); Digits (8B);
ASM_END(1B): Digits(8B);


string:
ASM_VALUE(1B): DAO_STRING(1B), MBS/WCS(1B), SizeMod16(1B), Bytes(5B);
  ASM_DATA(1B); Bytes(8B);
ASM_END(1B): Bytes(8B);


enum symbol:
ASM_VALUE(1B): DAO_ENUM(1B), Zeros(1B), Type-Index(2B), Zeros(4B);
ASM_END(1B): Value(4B), Zeros(0);
@[code]

Notes:


The "Type-Index" reference previous blocks which are located backwardly
by a such "index" offset. Only blocks that represent values are indexed,
and such index is stored as a two-byte short.


In case short is not sufficient to represent such index, an intermediate
indexing chunk can be used:

@[code]
ASM_SEEK(1B): New-Index(2B), Zeros(6B);
@[code]

When "New-Index" is also seeked backwardly, and is relative to the
seek chunk.


@[code]
array:
ASM_VALUE(1B): DAO_ARRAY(1B), Numeric-Type(1B), Dimensions(2B), Size(4B);
  ASM_DATA(1B); Dim1(4B), Dim2(4B);
  ASM_DATA(1B); More dimensions;
  ASM_DATA(1B); Data(4B), Data(4B); Or Data(8B);
  ASM_DATA(1B); More Data;
ASM_END(1B): Data(8B);


list:
ASM_VALUE(1B): DAO_LIST(1B), Zeros(1B), Type-Index(2B), Size(4B);
  ASM_DATA(1B); Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
ASM_END(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);


map:
ASM_VALUE(1B): DAO_MAP(1B), Zeros(1B), Type-Index(2B), Hash-Seed(4B);
  ASM_DATA(1B); Key-Index(2B), Value-Index(2B), Key-Index(2B), Value-Index(2B);
ASM_END(1B): Key-Index(2B), Value-Index(2B), Key-Index(2B), Value-Index(2B);

A pair of "Value-Index"s is for a pair of key-value, zero marks the end.


tuple:
ASM_VALUE(1B): DAO_TUPLE(1B), SubTypeID(1B), Type-Index(2B), Size(2B), Value-Index(2B);
  ASM_DATA(1B); Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
ASM_END(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);


namevalue:
ASM_VALUE(1B): DAO_PAR_NAMED(1B), Zeros(1B), Name-Index(2B), Value-Index(2B), Type-Index(2B);
ASM_END(1B): Zeros(8B);


specialized ctype:
ASM_VALUE(1B): DAO_CTYPE(1B), Zeros(1B), Value-Index(2B), Type-Index(2B) X 2;
  ASM_DATA(1B): Type-Index(2B) X 4;
ASM_END(1B): Type-Index(2B) X 4;
@[code]


@[subsection]
Other Values
@[subsection]

@[code]
copied value:
ASM_COPY(1B): Value-Index(2B), Zeros(6B);

type of a value:
ASM_TYPEOF(1B): Value-Index(2B), Zeros(6B);

type alias:
ASM_TYPEDEF(1B): Name-Index(2B), Type-Index(2B), Zeros(4B);
@[code]


@[subsection]
Structures:
@[subsection]

@[code]
routine:
ASM_ROUTINE(1B): Name-Index(2B), Type-Index(2B), Host-Index(2B), Attrib(2B);
  ...
ASM_END: RegCount(2B), Zeros(4B), DefaultConstructor(1B), Permission(1B);


class:
ASM_CLASS(1B): Name/Decl-Index(2B), Parent-Index(2B), Attrib(4B);
  ASM_BASES(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
  ...
ASM_END(1B): LineDef(2B), Zeros(5B), Permission(1B);


interface:
ASM_INTERFACE(1B): Name/Decl-Index(2B), Parent-Count(2B), Zeros(4B);
  ASM_BASES(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
  ...
ASM_END(1B): LineDef(2B), Zeros(5B), Permission(1B);


enum:
ASM_ENUM(1B): Name-Index(2B), Enum/Flag(2B), Count(4B);
  ASM_DATA(1B): Name-Index(2B), Value(4B), Zeros(2B);
ASM_END(1B): Name-Index(2B), Value(4B), Zeros(2B);


type:
ASM_TYPE(1B): Name-Index(2B), TypeID(2B), Aux-Index(2B), CodeBlockType-Index(2B);
  ASM_DATA(1B): Type-Index(2B) X 4;
ASM_END(1B): Type-Index(2B) X 4;

Note 1: the nested types are zero Type-Index terminated;
Note 2: "Aux-Index" could be index to returned type or class block etc;


type alias:
ASM_TYPE(1B): Name-Index(2B), Type-Index(2B), Zeros(4B);


typeof:
ASM_TYPE(1B): Value-Index(2B), Zeros(6B);


value:
See above;


evaluation:
ASM_EVAL(1B): Opcode(2B), OpB(2B), Type-Index(2B), Zeros(2B);
  ASM_DATA(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
ASM_END(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);


bases (mixin components or interface parents):
ASM_BASES(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
  ASM_DATA(1B): Value-Index(2B) X 4;
ASM_END(1B): Value-Index(2B) X 4;


decorators for the current routine:
ASM_DECOS(1B): Func-Index(2B), ParList-Index(2B), Func-Index(2B), ParList-Index(2B);
  ASM_DATA(1B): Func-Index(2B), ParList-Index(2B), Func-Index(2B), ParList-Index(2B);
ASM_END(1B): Func-Index(2B), ParList-Index(2B), Func-Index(2B), ParList-Index(2B);


patterns for automatic decorator application:
ASM_PATTERNS(1B): PatternString-Index(2B) X 4;
  ASM_DATA(1B): PatternString-Index(2B) X 4;
ASM_END(1B): PatternString-Index(2B) X 4;


consts:
ASM_CONSTS(1B): Count(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
  ASM_DATA(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);
ASM_END(1B): Value-Index(2B), Value-Index(2B), Value-Index(2B), Value-Index(2B);


types:
ASM_TYPES(1B): Count(2B), Zeros(2B), Var-Index(2B), Type-Index(2B);
  ASM_DATA(1B): Var-Index(2B), Type-Index(2B), Var-Index(2B), Type-Index(2B);
ASM_END(1B): Var-Index(2B), Type-Index(2B), Var-Index(2B), Type-Index(2B);


code:
ASM_CODE(1B): CodeNum(2B), Line-Num-Count(2B), LineNum(2B), Count(2B);
  ASM_DATA(1B): LineDiff(2B), Count(2B), LineDiff(2B), Count(2B);
  ASM_DATA(1B): Opcode(2B), A(2B), B(2B), C(2B);
ASM_END(1B): Opcode(2B), A(2B), B(2B), C(2B);
@[code]


@[subsection]
Statement:
@[subsection]

@[code]
load statement:
ASM_LOAD(1B): File-Path-Index(2B), Optional-Name-Index(2B), Zeros(4B);

use namespace:
ASM_USE(1B): DAO_NAMESPACE(2B), Value-Index(2B), Zeros(4B);

use enum constants:
ASM_USE(1B): DAO_ENUM(2B), Type-Index(2B), Zeros(4B);

use constructors:
ASM_USE(1B): DAO_ROUTINE(2B), Routine-Index(2B), Zeros(4B);

verbatim:
ASM_VERBATIM(1B): Tag-Index(2B), Mode-Index(2B), Text-Index(2B), LineNum(2B);

var declaration:
ASM_VAR(1B): Name-Index(2B), Value-Index(2B), Type-Index(2B), Scope(1B), Perm(1B);

const declaration:
ASM_CONST(1B): Name-Index(2B), Value-Index(2B), Zeros(2B), Scope(1B), Permission(1B);

static declaration:
ASM_STATIC(1B): Name-Index(2B), Value-Index(2B), Type-Index(2B), Scope(1B), Perm(1B);

global declaration:
ASM_GLOBAL(1B): Name-Index(2B), Value-Index(2B), Type-Index(2B), Scope(1B), Perm(1B);

seek:
ASM_SEEK(1B): New-Index(2B), Zeros(6B);
@[code]


@[section]
Samples
@[section]

Input code:
@[code]
io.writeln( 'Hello Dao!' );
@[code]

Output disassembled bytecode:
@[code]
ASM_ROUTINE: 0, 0, 0, 512;
    ASM_VALUE: DAO_STRING, 0, 2, 'io';
    ASM_END: '';

    ASM_EVAL: GETCG, 1, 0, 0;
    ASM_END:      1,     0,     0,     0;

    ASM_VALUE: DAO_STRING, 0, 7, 'write';
    ASM_END: 'ln';

    ASM_EVAL: GETF, 2, 0, 0;
    ASM_END:      2,     1,     0,     0;

    ASM_VALUE: DAO_STRING, 0, 10, 'Hello';
    ASM_END: ' Dao!';

    ASM_CONSTS:      2,     2,     1,     0;
    ASM_END:         0,     0,     0,     0;

    ASM_TYPES:      0,     0,     0,     0;
    ASM_END:        0,     0,     0,     0;

    ASM_CODE:      6,     1,     1,     6;
        ASM_DATA:    GETCG      ,     1,     5,     0;
        ASM_DATA:    GETCL      ,     0,     0,     1;
        ASM_DATA:    LOAD       ,     0,     0,     2;
        ASM_DATA:    GETCL      ,     0,     1,     3;
        ASM_DATA:    MCALL      ,     1, 16386,     4;
    ASM_END:         RETURN     ,     0,     0,     0;
ASM_END:  ;
@[code]


Input code:
@[code]
load web.cgi

enum Bool
{
	False,
	True
}

use enum Bool

static abc = random_string( 100 )

global index = 123 + %abc

class Klass
{
  const  name = "abc"; 
  var    index = 123;

  routine Method( a :int ){
  }
}

routine Func()
{
    name = index
}

klass = Klass()
@[code]

Output disassembled bytecode:
@[code]
ASM_ROUTINE: 0, 0, 0, 1536;
    ASM_VALUE: DAO_STRING, 0, 7, 'web/c';
    ASM_END: 'gi';

    ASM_LOAD:     1,     0,     0,     0;

    ASM_VALUE: DAO_STRING, 0, 4, 'Bool';
    ASM_END: '';

    ASM_VALUE: DAO_STRING, 0, 5, 'False';
    ASM_END: '';

    ASM_VALUE: DAO_STRING, 0, 4, 'True';
    ASM_END: '';

    ASM_VALUE: DAO_STRING, 0, 0, 'enum<';
        ASM_DATA: 'False,Tr';
    ASM_END: 'ue>';

    ASM_ENUM: 1, 0, 2;
        ASM_DATA: 3, 0;
    ASM_END: 2, 1;

    ASM_TYPEDEF:     5,     1,     0,     0;

    ASM_USE:     7,     1,     0,     0;

    ASM_VALUE: DAO_STRING, 0, 13, 'rando';
    ASM_END: 'm_string';

    ASM_EVAL: GETCG, 1, 0, 0;
    ASM_END:      1,     0,     0,     0;

    ASM_VALUE: DAO_INTEGER;
    ASM_END:  100 ;

    ASM_VALUE: DAO_STRING, 0, 1, '?';
    ASM_END: '';

    ASM_TYPE:      1,    66,     0,     0;
    ASM_END:       0,     0,     0,     0;

    ASM_EVAL: CALL, 1, 1, 0;
    ASM_END:      4,     3,     0,     0;

    ASM_TYPEOF:     1,     0,     0,     0;

    ASM_VALUE: DAO_STRING, 0, 3, 'abc';
    ASM_END: '';

    ASM_STATIC:     1,     3,     2,     0;

    ASM_VALUE: DAO_STRING, 0, 5, 'index';
    ASM_END: '';

    ASM_GLOBAL:     1,     0,     5,     3;

    ASM_VALUE: DAO_STRING, 0, 5, 'Klass';
    ASM_END: '';

    ASM_CLASS: 1, 0, 0, 0;
    ASM_END:  ;

    ASM_VALUE: DAO_STRING, 0, 0, 'inter';
        ASM_DATA: 'face<Kla';
    ASM_END: 'ss>';

    ASM_INTERFACE: 2, 0, 0, 0;
        ASM_BASES:      0,     0,     0,     0;
        ASM_END:        0,     0,     0,     0;
    ASM_END:  ;

    ASM_CLASS: 3, 0, 0, 1;
        ASM_BASES:      0,     0,     0,     0;
        ASM_END:        0,     0,     0,     0;

        ASM_VALUE: DAO_STRING, 0, 4, 'name';
        ASM_END: '';

        ASM_VALUE: DAO_STRING, 1, 3, "a";
        ASM_END: "bb";

        ASM_CONST:     2,     1,     0,     3;

        ASM_VALUE: DAO_INTEGER;
        ASM_END:  123 ;

        ASM_VALUE: DAO_STRING, 0, 3, 'int';
        ASM_END: '';

        ASM_TYPE:      1,     1,     0,     0;
        ASM_END:       0,     0,     0,     0;

        ASM_VAR:    11,     3,     1,     3;

        ASM_TYPE:     10,    12,     6,     0;
        ASM_END:       0,     0,     0,     0;

        ASM_VALUE: DAO_STRING, 0, 10, 'self:';
        ASM_END: 'Klass';

        ASM_TYPE:      1,    30,     2,     0;
        ASM_END:       0,     0,     0,     0;

        ASM_VALUE: DAO_STRING, 0, 5, 'a:int';
        ASM_END: '';

        ASM_TYPE:      1,    30,     5,     0;
        ASM_END:       0,     0,     0,     0;

        ASM_VALUE: DAO_STRING, 0, 12, 'routi';
            ASM_DATA: 'ne<self:';
            ASM_DATA: 'Klass,a:';
        ASM_END: 'int=>?>';

        ASM_TYPE:      1,    18,    21,     0;
        ASM_END:       4,     2,     0,     0;

        ASM_VALUE: DAO_STRING, 0, 6, 'Metho';
        ASM_END: 'd';

        ASM_ROUTINE: 1, 2, 8, 1;
        ASM_END:  ;

        ASM_ROUTINE: 1, 3, 9, 1;
            ASM_CONSTS:      2,     0,     0,     0;
            ASM_END:         0,     0,     0,     0;

            ASM_TYPES:      2,     0,     0,     8;
            ASM_END:        1,    11,     0,     0;

            ASM_CODE:      1,     1,     0,     1;
            ASM_END:         RETURN     ,     0,     0,     0;
        ASM_END:  ;

        ASM_VALUE: DAO_STRING, 0, 0, 'routi';
            ASM_DATA: 'ne<=>Kla';
        ASM_END: 'ss>';

        ASM_TYPE:      1,    18,    11,     0;
        ASM_END:       0,     0,     0,     0;

        ASM_VALUE: DAO_STRING, 0, 12, 'Klass';
        ASM_END: '::Klass';

        ASM_ROUTINE: 1, 2, 13, 256;
            ASM_CONSTS:      0,     0,     0,     0;
            ASM_END:         0,     0,     0,     0;

            ASM_TYPES:      0,     0,     0,     0;
            ASM_END:        0,     0,     0,     0;

            ASM_CODE:      1,     1,     0,     1;
            ASM_END:         RETURN     ,     0,     0,     0;
        ASM_END:  ;
    ASM_END:  ;

    ASM_VALUE: DAO_STRING, 0, 12, 'routi';
    ASM_END: 'ne<=>?>';

    ASM_TYPE:      1,    18,    30,     0;
    ASM_END:       0,     0,     0,     0;

    ASM_VALUE: DAO_STRING, 0, 4, 'Func';
    ASM_END: '';

    ASM_ROUTINE: 1, 2, 0, 0;
        ASM_CONSTS:      0,     0,     0,     0;
        ASM_END:         0,     0,     0,     0;

        ASM_TYPES:      0,     0,     0,     0;
        ASM_END:        0,     0,     0,     0;

        ASM_CODE:      3,     1,    26,     3;
            ASM_DATA:    GETVG      ,     0,    29,     0;
            ASM_DATA:    MOVE_XX    ,     0,     0,     1;
        ASM_END:         RETURN     ,     0,     0,     0;
    ASM_END:  ;

    ASM_CONSTS:      1,    24,     0,     0;
    ASM_END:         0,     0,     0,     0;

    ASM_TYPES:      0,     0,     0,     0;
    ASM_END:        0,     0,     0,     0;

    ASM_CODE:     10,     3,     9,     1;
        ASM_DATA:      4,     5,    16,     4;
        ASM_DATA:    GETCG      ,     0,    43,     0;
        ASM_DATA:    DATA_I     ,     1,   123,     1;
        ASM_DATA:    GETVS      ,     0,     0,     2;
        ASM_DATA:    SIZE       ,     2,     0,     3;
        ASM_DATA:    ADD_III    ,     1,     3,     4;
        ASM_DATA:    SETVG_II   ,     4,     7,     0;
        ASM_DATA:    GETCL      ,     0,     0,     5;
        ASM_DATA:    CALL       ,     5,     0,     6;
        ASM_DATA:    MOVE_PP    ,     6,     0,     7;
    ASM_END:         RETURN     ,     0,     0,     0;
ASM_END:  ;
@[code]

@[text]
