# HOWTOs

# 1. How to debug

By default, legitimate contract calls will be executed at the agent node, but ordinary nodes can also manually open the contract virtual machine, verify the contract call in the blockchain, and execute the contract call.

Simple debugging methods can output variables through pprint, for basic types pprint will output a string representation of multiple parameter values, for functions will output the memory address of the function, for table type values will be converted to json string output.

Later, the remote debugging function will be added, and the process interruption point debugging will be run on the remote agent node.

# 2. How to use event

The contract can be thrown through emit EventName (EventArg). EventName is a custom event name. The lexical requirements for event names are the same as the variable name requirements, but the maximum length is 49 characters. EventArg is the parameter of the event. The required value is 1024 characters. String

The event thrown during the execution of the operation calling the contract will be recorded in the blockchain. The local node of the blockchain can set a callback script to monitor an event of a contract, and then synchronize it on the blockchain to include the monitored event The block will trigger the set script, and the callback script is also written in hvm.

# 3. What are the common compilation errors

  • Variable type and assignment are inconsistent
  • The parameter type of the function call is inconsistent with the actual parameter type
  • The function parameter type and the type used in the function body are inconsistent. It is recommended that the function parameter plus an explicit type declaration
  • Some code blocks are missing end
  • Variables that have not been declared are used
  • Global variables are defined in the contract (new global variables are not allowed in the contract and can only be read, but new global variables can be defined in the script)
  • Perform some disallowed operator operations on nil values, such as addition, subtraction, multiplication and division
  • Access attributes of non-table values
  • other

# 4. How to support Chinese or other non-English

Variable names, function names, and event names cannot use Chinese. They can only start with English characters or underscores, followed by several English characters or underscores or numbers, but the contents of the string can be written in Chinese or other languages. Unicode is supported.

# 5. Does it support multithreading?

Because hvm is mainly for running on the nodes of the blockchain, considering the characteristics of the blockchain, especially for reaching consensus, multi-threaded programming is not supported

# 6. How to use random numbers in hvm

Provide two ways to get random numbers

  • The global function get_chain_random() obtains a pseudo-random number on the chain. The random number returned by this function is a result that can be extrapolated. It is only used where only uniformly distributed numbers need to be returned
  • The global function get_waited(blocknumber) can obtain an int32 number generated according to the binary content of the block number of the specified block. The parameter can be the past block or the block number of the future block. To obtain the random number in this way, you can call the global function get_header_block_num() gets the block number of the previous block, then calls the get_waited function with a future block number (current block number plus the number of future blocks, about 10 seconds per block) as the parameter, if the current block is executed If the chain has not reached this block number, it returns -1. If the current block chain has exceeded this block number during execution, it returns an int32 number generated from the data on that block. Take the lottery as an example, set the get_waited parameter to the future block number of the expected draw time, and then allow betting some time before the draw. At this time, the block number of the get_waited parameter has not yet reached this block, the return type is -1, everyone I don't know what the result of this function call will be after the draw time. When the start time is up, the return result of calling get_waited is fixed to a positive number of type int32, and any subsequent node call results with the same parameter are fixed, and the random number is determined. You can use this return value (result% 10000) / 10000 to obtain a random number with precision of 4 decimal places between (0, 1)

# 7. How to implement object-oriented type inheritance and polymorphism

You can use table type and record type to simulate objects. The record type has a default attribute value, and the attribute can be a function with a default implementation.

such as

type Person = {
    id: string default "123",
    name: string default "hvm",
    age ?: int = 24,  -- The default value of the record attribute can be either default or = to distinguish
    fn: (number, number) => number default 
            function (a: number, b: number) 
                return a + b
            end
}

let p = Person()
pprint(p.id, p.name, p.age)
let n = p.fn(p.age, 2016)
pprint(n)

If you need to implement the type inheritance and polymorphism functions in an object-oriented language, you can implement an extend function. After calling the constructor of the child record type, use the extend function to accept the child object and the parent type, and create a new parent in the extend function Objects of the type, and then assign attributes to the child type objects that are not in the child type object of the parent type object. In this way, inheritance and polymorphism can be achieved. There is no standard extend function currently given, an example implementation is given

let function extend(obj, parent_class)
    let parent = parent_class(obj)
    for k, v in pairs(parent) do
        obj[k] = v
    return totable(obj)
end

type A = {
    name1: string,
    age1: int default 100
}

type B = {
    name: string,
    age: int
}

let b = B()
extend(b, A)

-- or

let c = extend(B(), A)

There is another way to implement type inheritance and polymorphism is to use setmetatable and metatable, which will be given more documents and examples later