Disassembler
When Scriggo runs a program or template, first compiles it into a bytecode and then runs it on the Scriggo Virtual Machine.
How to disassemble
To disassemble a program or a template you can:
-
in the Scriggo Playground click on the
Disassemble
button to show the disassembled program. -
with the scriggo package, call the method
Disassemble
on the value returned by theBuild
method to disassemble a named package:asm, err = program.Disassemble("main")
-
with the scriggo package, call the method
Disassemble
on the value returned by theBuildTemplate
method to disassemble the template:asm = template.Disassemble(-1)
Registers
The Scriggo Virtual Machine has 500 registers for each called function to store its local variables:
- 125 integer registers:
i1
,i2
, ...,i125
- 125 floating-point registers:
f1
,f2
, ...,f125
- 125 string registers:
s1
,s2
, ...,s125
- 125 general registers:
g1
,g2
, ...,g125
Local variables with basic type an integer or boolean type are stored in the int registers:
var a int
var b uint32
var c rune
var d time.Duration = 5 * time.Second
var e bool // false is stored as 0
var f MyBool = true // true is stored as 1
Local variables with basic type a floating-point type are stored in the float registers:
var a float32
var b float64
var d MyFloat = 3.2
Local variables with basic type string are stored in the string registers:
var a string
var b MyString = "hello"
All other local variables are stored in the general registers:
var a []int
var b map[string]string
var c interface{}
var d time.Time
var e *S
ok flag
In addition to the registers for called functions, there is special boolean ok
flag used by Assert
, If
, MapIndex
, Select
, Range
and Receive
instructions.
Package clause
The clause Package
begins a disassembled code and defines the package to which the code belongs.
Syntax: Package name ; description: package name
Import declaration
The declaration Import
states that the disassembled package uses exported identifiers of the imported package.
Syntax: Import "pkg" ; description: import "pkg"
Func declaration
The declaration Func
declares a function with its body and specifies the number of registers that it uses.
Syntax: Func f(a1, ...an) (r1, ...rn) ; func f(a1, ...an) (r1, ...rn)
; regs(ni,nf,ns,ng)
Example: Func sum(i1, i2 int) (i3 int)
; regs(3,0,0,0)
Macro declaration
The declaration Macro
declares a macro with its body and specifies the number of registers that it uses.
Syntax: Macro m(a1, ...an) T ; {% macro m(a1, ...an) T %} ... {% end %}
; regs(ni,nf,ns,ng)
Example: Macro Head(s5 markdown) (s7 markdown)
; regs(1,0,3,0)
Assembly instructions
The Scriggo assembly is an abstraction above the virtual machine instructions. Some assembly instructions have a direct representation in a virtual machine instruction but some do not.
There are 72 assembly instructions:
- Add
- Addr
- And
- AndNot
- Append
- AppendSlice
- Assert
- Break
- Call
- Cap
- Case
- Close
- Complex64
- Complex128
- Continue
- ConvertNumber
- ConvertSlice
- ConvertString
- Concat
- Copy
- Defer
- Delete
- Div
- Field
- Func
- GetVar
- GetVarAddr
- Go
- Goto
- If
- Index
- Len
- Load
- LoadFunc
- MakeArray
- MakeChan
- MakeMap
- MakeSlice
- MakeStruct
- MapIndex
- MethodValue
- Move
- Mul
- Neg
- New
- NotZero
- Or
- Panic
- Range
- RealImag
- Receive
- Recover
- Rem
- Return
- Select
- Send
- SetField
- SetMap
- SetSlice
- SetVar
- Shl
- Show
- Shr
- Slice
- Sub
- SubInv
- TailCall
- Text
- Typify
- Xor
- Zero
Add
The instruction Add
sums two integers or two floats. Add
has two forms.
The first form sums the operands addressed by a
and b
and stores the result in c
, the type of operands is int
or float64
.
The second form adds the operand addressed by b
and c
and stores the result in c
. type
is the type of the operands.
b
can be an integer constant between 0 and 255.
Syntax: Add a b c ; description: c = a + b // int and float64 types
Add type b c ; description: c += b
Example: Add i12 8 i7
Add f2 f9 f5
Add uint8 i2 i6
Add float32 50 f2
Addr
The instruction Addr
takes the address of a slice element or struct pointer field and stores it in p
. For slices, the slice is addressed by s
and the index of the element is addressed by i
. For struct pointers, the struct pointer is addressed by s
and the field index is addressed by i
.
Syntax: Addr s i p ; description: p = &s[i]
Addr s i p ; p = &s.f // where f if the field of s at index i
And
The instruction And
computes the bitwise AND of the operands addressed by a
and b
and stores the result in c
.
Syntax: And a b c ; description: c = a & b
AndNot
The instruction AndNot
computes the AND NOT (bit clear) of the operands addressed by a
and b
and stores the result in c
.
Syntax: AndNot a b c ; description: c = a &^ b
Append
The instruction Append
appends values to the slice addressed by s
and store the resulting slice in s
. The appended values are the values in the registers starting from the register start
and ending to the register end
. The registers with the values to append are consecutive and their type depends on the type of the slice's element.
Syntax: Append start end s ; description: s = append(s, start, ..., end)
Example: Append s3 s5 g2 ; append the values in the s3, s4 and s5 registers
AppendSlice
The instruction AppendSlice
appends the slice addressed by s1
to the slice addressed by s2
and stores the resulting slice in s2
.
Syntax: AppendSlice s1 s2 ; description: s2 = append(s2, s1...)
Assert
The instruction Assert
asserts that the value addressed by x
is not nil
and it is of type T
.
Syntax: Assert x T v ; description: v, ok = x.(T)
If the type assertion holds, it stores the resulting value into the register v
(the register type depends on the type T
), sets the ok
flag to true
and skips the next instruction.
If the type assertion is false, it sets the ok
flag to false
and, if the next instruction is a Panic
, does a run-time panic.
Break
The instruction Break
breaks a previous executed Range
instruction at label label
.
Syntax: Break label ; description: break label
Call
The instruction Call
calls the function, or macro, with name name
or the function, or macro, addressed by fn
with arguments addressed by i
, f
, s
and g
.
i
is the first integer register of the integer parameters.f
is the first floating point register of the floating point parameters.s
is the first string register of the string parameters.g
is the first general register of the other parameters.
i
, f
, s
and g
may be the blank identifier if there are no such arguments.
Syntax: Call name i f s g ; description: name(...)
Call (fn) i f s g ; fn(...)
Example: Call fmt.Printf _ _ s3 g2
Call (g8) i2 _ s4 _
In a function call, consecutive registers are used to store the return values and the arguments to the function. For example for a call to the function sum
:
func sum(a, b int) int {
return a + b
}
three consecutive integer register are used for the parameters. The first is reserved for the return parameter, the second and third for the parameters a
and b
. So the following example:
s := sum(1, 2)
print(s)
could be compiled to:
Move 1 i6 ; store a into the register i6
Move 2 i7 ; store b into the register i7
Call sum i5 _ _ _ ; call sum
Print i5 ; print the return value stored in the register i5
where the register i5
is reserved for the return parameter, the registers i6
and i7
respectively for the parameters a
and b
.
This little more complex example:
split := strings.SplitN("a,b,c", ",", 2)
n := len(split)
could be compiled to:
Move "a,b,c" s5 ; store the string to split into s5
Move "," s6 ; store the separator into s6
Move 2 i3 ; store the count into i3
Call strings.SplitN i3 _ s5 g2 ; call strings.SplitN
Len g2 i2 ; get the length of the returned slice
Cap
The instruction Cap
gets the cap of the slice or channel addresses by s
and stores it in c
.
Syntax: Cap s c ; description: c = cap(s)
Case
The instruction Case
defines a new case that can be chosen by a subsequent Select
instruction.
If the instruction Select
chooses a Send
case, it sends the value addressed by v
to the channel ch
.
If the instruction Select
chooses a Recv
case, it receives from the channel addressed by ch
and stores the value in v
.
If the instruction Select
chooses a Default
case, it does nothing.
See the Select instruction for how to use Case
with Select
.
Syntax: Case Send v ch ; description: case ch <- v:
Case Recv ch v ; description: case v = <-ch:
Case Default ; description: default:
Close
The instruction Close
closes the channel addressed by ch
. Closing a closed channel or a nil
channel causes a run-time panic.
Syntax: Close ch ; description: close(ch)
Complex64
The instruction Complex64
assembles a complex64
value from the float32
values addressed by re
and im
and stores the resulting complex in c
.
Syntax: Complex64 re im c ; description: c = complex(re, im)
Complex128
The instruction Complex128
assembles a complex128
value from the float64
values addressed by re
and im
and stores the resulting complex in c
.
Syntax: Complex128 re im c ; description: c = complex(re, im)
Continue
The instruction Continue
begins the next iteration of the previous executed Range
instruction at label label
.
Syntax: Continue label ; description: continue label
ConvertNumber
The instruction ConvertNumber
explicitly converts the numeric operand addressed by x
from the kind xKind
to the kind yKind
and stores it in y
.
Syntax: ConvertNumber x xKind yKind y
xKind
and yKind
can be Int
, Int8
, Int16
, Int32
, Uint
, Uint8
, Uint16
, Uint32
, Float32
, Float64
, Complex64
or Complex128
. yKind
can also be String
if xKind
is a integer kind.
Example: ConvertNumber i7 Int32 Uint i4
ConvertNumber f2 Float64 Float32 f6
ConvertNumber g5 Complex128 Complex64 g4
ConvertNumber f11 Float32 Complex128 g2
ConvertNumber i3 Int String s7
ConvertSlice
The instruction ConvertSlice
explicitly converts the slice of bytes or runes addressed by x
to a value of type string
and stores it in y
.
Syntax: ConvertSlice x y ; description: y = string(x)
ConvertString
The instruction ConvertString
explicitly converts the string operand addressed by x
to a slice of bytes or runes value of type T
and stores it in y
.
As a special case, if T
is the format type html
, ConvertString
explicitly converts a value of type markdown
to a value of type html
.
Syntax: ConvertString x T y ; description: y = T(x)
Example: ConvertString s3 []byte g5
ConvertString s8 []rune g2
ConvertString s6 html s7
Concat
The instruction Concat
concatenates the string operands addressed by s1
and s2
and stores the resulting string in s3
.
Syntax: Concat s1 s2 s3 ; description: s3 = s1 + s2
Copy
The instruction Copy
copies the elements of the slice addressed by src
to the slice addressed by dst
. If the operand n
is not zero, Copy
stores in the integer register addressed by n
the number of elements copied .
Syntax: Copy src n dst ; description: n = copy(dst, src)
Defer
The instruction Defer
defers the execution of the function addressed by f
.
Syntax: Defer f ; description: defer f() { ... }
TODO: to be completed.
Delete
The instruction Delete
removes from the map addressed by m
the element with key addressed by k
.
Syntax: Delete m k ; description: delete(m, k)
Div
The instruction Div
divides two integers or two floats. Div
has two forms.
The first form divides the operands addressed by a
and the operand addressed by b
and stores the result in c
, the type of operands is int
or float64
.
The second form divides the operand addressed by c
and the operand addressed by b
and stores the result in c
. type
is the type of the operands.
b
can be an integer constant between -128 and 127, excluding zero.
Syntax: Div a b c ; description: c = a / b // int and float64 types
Div type b c ; description: c /= b
Example: Div i10 4 i7
Div f3 f4 f5
Div int8 -6 i3
Div float64 f2 f1
Field
The instruction Field
gets from the struct pointer referred by s
the field at the index referred by i
and stores its value in v
.
Syntax: Field s i v ; description: v = s.f // where f is the field of s at index i
Func
The instruction Func
combines a function literal declaration with a load of the function (a closure to be precise) into fn
.
Syntax: Func fn ; description: fn = func(...) { ... }
<function body>
Example: Move 2 i1
Func g3
Move 2 i3
Add i1 1 i2
Return
Call (g3) i1 _ _ _
See the LoadFunc instruction for how to load a non-literal function.
GetVar
The instruction GetVar
gets (TODO).
Syntax: GetVar i c ; description:
GetVarAddr
The instruction GetVarAddr
gets (TODO).
Syntax: GetVarAddr i c ; description:
Go
The instruction Go
runs the following Call
or CallIndirect
instruction in a new goroutine.
Syntax: Go ; description: go
Example:
Go
Call Serve i2 _ s1 _
Goto
The instruction Goto
transfers control to the instruction with the corresponding label within the same function.
Syntax: Goto label ; description: goto label
If
The instruction If
checks its condition and skips the next instruction if it is satisfied.
Syntax: If Zero a ; description: if a == 0
If NotZero a ; if a != 0
If Nil a ; if a == nil
If NotNil a ; if a != nil
If NilInterface a ; if a == nil // a has an interface type
If NotNilInterface a ; if a != nil // a has an interface type
If a Equal b ; if a == b
If a NotEqual b ; if a != b
If a Less b ; if a < b
If a LessEqual b ; if a <= b
If a Greater b ; if a > b
If a GreaterEqual b ; if a >= b
If a LenEqual b ; if len(a) == b
If a LenNotEqual b ; if len(a) != b
If a LenLess b ; if len(a) < b
If a LenLessEqual b ; if len(a) <= b
If a LenGreater b ; if len(a) > b
If a LenGreaterEqual b ; if len(a) >= b
If a ContainsSubstring b ; if a contains b // as substring
If a ContainsRune b ; if a contains b // as rune
If a ContainsElement b ; if a contains b // as element
If a ContainsKey b ; if a contains b // as key
If a ContainsNil ; if a contains nil // as element or key
If a NotContainsSubstring b ; if a not contains b // as substring
If a NotContainsRune b ; if a not contains b // as rune
If a NotContainsElement b ; if a not contains b // as element
If a NotContainsKey b ; if a not contains b // as key
If a NotContainsNil ; if a not contains nil // as element or key
If OK ; if ok // ok is the ok flag
If NotOK ; if !ok // ok is the ok flag
Index
The instruction Index
gets, from the slice or string referred by s
, the element at the index referred by i
and stores its value in v
.
Syntax: Index s i v ; description: v = s[i]
Len
The instruction Len
gets the length of the slice, string or channel addressed by s
and stores it in n
.
Syntax: Len s n ; description: n = len(s)
Load
The instruction Load
loads a value v
and stores it by copy into dst
.
Syntax: Load v dst ; description: dst = v
Example: Load 64 i3
Load 3.14 f7
Load "a" s1
Load [2]int{} g3
Load nil g5
LoadFunc
The instruction LoadFunc
loads the function with name name
into fn
.
Syntax: LoadFunc name fn ; description: fn = name
Example: LoadFunc strings.HasPrefix g2
Call (g2) i1 _ s3 _
See the Func instruction for how to declare and load a function literal.
MakeArray
The instruction MakeArray
makes an array with type T
and stores it in a
.
Syntax: MakeArray T a ; description: var a T
MakeChan
The instruction MakeChan
makes a channel with type T
and buffer size addressed by s
and stores it in ch
.
Syntax: MakeChan T s ch ; description: ch = make(T, s)
MakeMap
The instruction MakeMap
makes a map with type T
and size addressed by s
and stores it in m
.
Syntax: MakeMap T s m ; description: m = make(T, s)
MakeSlice
The instruction MakeSlice
makes a slice with element type T
, length addressed by n
, cap addressed by c
and stores it in s
.
Syntax: MakeSlice T n c s ; description: s = make(T, n, c)
MakeStruct
The instruction MakeStruct
makes a struct with type T
and stores it in s
.
Syntax: MakeStruct T s ; description: var s T
MapIndex
The instruction MapIndex
gets from the map addressed by m
the element with key addressed by k
and stores its value in v
. Also, it sets the ok
flag to true
if the key exists or false
if key does not exist.
Syntax: MapIndex m k v ; description: v = m[k]
MethodValue
TODO
Move
The instruction Move
copies the value addressed by s
to d
.
Syntax: Move s d ; description: d = s
Mul
The instruction Mul
multiplies two integers or two floats. Mul
has two forms.
The first form multiplies the operands addressed by a
and the operand addressed by b
and stores the result in c
, the type of operands is int
or float64
.
The second form multiplies the operand addressed by c
and the operand addressed by b
and stores the result in c
. type
is the type of the operands.
b
can be an integer constant between -128 and 127.
Syntax: Mul a b c ; description: c = a * b // int and float64 types
Mul type b c ; description: c *= b
Example: Mul i2 i4 i3
Mul f9 12 f2
Mul uint16 i3 i1
Mul float32 f5 f6
Neg
The instruction Neg
negates the operand addresses by b
, with an integer or floating point type, and stores the result into c
.
If b
does not have int
or float64
type, type
indicates its type.
Syntax: Neg b c ; description: c = -b // for int and float64 types
Neg type b c ; description: c = -b // for the other integer and floating point types
Example: Neg f2 f3
Neg i4 i4
Neg float32 f5 f8
New
The instruction New
allocates storage for a variable of type T
and stores a pointer to this variable in v
.
Syntax: New T v ; description: v = new(T)
NotZero
The instruction NotZero
checks if the value addressed by the register b
is not a zero value; if so, then stores 1
in the integer register c
, otherwise stores 0
.
As special cases, if the value addressed by b
is an empty slice or an empty
channel the instruction NotZero
stores 0
.
Moreover, if the value addressed by b
has type interface and it is not nil
,
the instruction NotZero
evaluates its dynamic value.
Syntax: NotZero b c ; description: c = 1 if b is not the zero value for its type
c = 0 otherwise
Example: NotZero i1 i2
NotZero s1 i3
See also the Zero instruction.
Or
The instruction Or
computes the bitwise OR of the operands addressed by a
and b
and stores the result in c
.
Syntax: Or a b c ; description: c = a | b
Panic
The instruction Panic
panics with the value addressed by v
.
Syntax: Panic v ; description: panic(v)
The instruction Print
formats the operand addressed by v
as does the built-in print
and writes the result to standard error.
Syntax: Print v ; description: print(v)
Range
The instruction Range
does an iteration through the entries of a slice, string, map or channel.
- For a slice, the iteration is on the slice addressed by
s
and the instructionRange
stores the iteration index ini
and the element ine
. - For a string, the iteration is on the string addressed by
s
and the instructionRange
stores the iteration index ini
and the rune inr
. - For a map, the iteration is on the map addressed by
m
and the instructionRange
stores the key ink
and the value inv
. - For a channel, the iteration is on the values received on the channel addressed by
ch
and the instructionRange
stores the value inv
.
If there are no elements to iterate over, it sets the vm.ok
flag to false
, otherwise it sets the flag to true
.
The instruction that follow Range
is executed only when there are no more values to iterate over, during the iteration this instruction is skipped.
The second and third operands can be the blank identifier.
Syntax: Range s i e ; description: for i, e = range s // for a slice
Range s i r ; description: for i, r = range s // for a string
Range m k v ; description: for k, v = range m // for a map
Range ch v ; description: for v = range ch // for a channel
The instruction Range
is used in combination to the instructions Goto
, Continue
and Break
to implement a for range
statement.
For example a range over the first five elements of a slice:
for i, e := range s {
if i == 5 {
break
}
print(i)
print(e)
}
return
could be compiled to assembly:
1: Range g2 i1 s7
Goto 3
If i1 Equal 5
Goto 2
Break 1
2: Print i1
Print s7
Continue 1
3: Return
RealImag
The instruction RealImag
extracts the real and imaginary parts of the complex number addressed by c
and stores the real part in re
and the imaginary part in im
.
Syntax: RealImag c re im ; description: re, im = real(c), imag(c)
Receive
The instruction Receive
receive a value from the channel addressed by ch
and stores the value in v
. Also it sets the ok
flag to true
if the value received was delivered by a successful send operation, or false
if a zero value was stored in v
because the channel is closed and empty.
Syntax: Receive ch v ; description: v, ok = <-ch
Recover
The instruction Recover
recovers a panicking goroutine and stores in v
the value passed to the call of panic. If the goroutine is not panicking or Recover
was not executed directly by a deferred function it stores nil
in v
. v
can be the blank identifier.
Syntax: Recover v ; description: v = recover()
As a special case, compiling the statement defer recover()
the following assembly line is generated:
Recover DownTheStack v
Rem
The instruction Rem
computes the remainder of two integers. Rem
has two forms.
The first form computes the remainder of the operands addressed by a
and the operand addressed by b
and stores the result in c
, the type of operands is int
.
The second form computes the remainder of the operand addressed by c
and the operand addressed by b
and stores the result in c
. type
is the type of the operands.
b
can be an integer constant between 1 and 255.
Syntax: Rem a b c ; description: c = a % b // int type
Rem type b c ; description: c %= b
Example: Rem i10 12 i2
Rem uint32 i7 i8
Return
The instruction Return
returns from the current running function. Any functions deferred with the Defer
instruction in the current function are executed before returning.
Syntax: Return ; description: return
Select
The instruction Select
selects a case from one of the cases defined by previously executed Case
instructions, executes a send or receive depending on the case, clears all the cases previously defined and jumps to the instruction that follows the selected Case
instruction.
Syntax: Select ; description: select
The instruction Select
is used in combination to the instruction Case to implement a select
statement.
For example the select statement:
select {
case a <-tick:
print(a)
case b <-boom:
print(b)
default:
print(3)
}
return
could be compiled to this assembly:
Case Recv i5 g2 ; case a <-tick:
Goto 1
Case Recv s3 g1 ; case b <-boom:
Goto 2
Case Default ; default
Goto 3
Select ; select
1: Print i5 ; print(a)
Goto 4
2: Print s3 ; print(b)
Goto 4
3: Print 3 ; print(3)
Goto 4
4: Return ; return
Send
The instruction Send
sends the value addressed by v
on the channel ch
.
Syntax: Send v ch ; description: ch <- v
SetField
The instruction SetField
stores the value addressed by v
into the field with index i
of the struct addressed by s
.
Syntax: SetField v s i ; description: s.f = v // where f is the field of s at index i
SetMap
The instruction SetMap
sets the value of the map addressed by m
and indexed by the key k
with the value addressed by v
.
Syntax: SetMap v m k ; description: m[k] = v
SetSlice
The instruction SetSlice
sets the value of the slice addressed by s
at the index i
with the value addressed by v
.
Syntax: SetSlice v s i ; description: s[i] = v
SetVar
The instruction SetVar
sets the value of the global or closure variable at index i
with the value addressed by v
.
Syntax: SetVar v i ; description: vars[i] = v
Shl
The instruction Shl
computes the left shift of an integer. Shl
has two forms.
The first form computes the left shift of the operands addressed by a
with shift count n
and stores the result in c
, the type of operands a
and c
is int
.
The second form computes the left shift of the operand addressed by c
with shift count n
and stores the result in c
. type
is the type of c
.
n
can be an integer constant between 0 and 255.
Syntax: Shl a n c ; description: c = a << n // int type
Shl type n c ; description: c <<= n
Example: Shl i3 5 i2
Shl uint16 i5 i6
Show
The instruction Show
formats the value addresses by v
based on the context ctx
and writes the result to the template out writer.
Syntax: Show T v (ctx); description: out.Write(format(v, ctx))
Shr
The instruction Shr
computes the right shift of an integer. Shr
has two forms.
The first form computes the right shift of the operands addressed by a
with shift count n
and stores the result in c
, the type of operands a
and c
is int
.
The second form computes the right shift of the operand addressed by c
with shift count n
and stores the result in c
. type
is the type of c
.
n
can be an integer constant between 0 and 255.
Syntax: Shr a n c ; description: c = a >> n // int type
Shr type n c ; description: c >>= n
Example: Shr i7 2 i3
Shr int8 i9 i3
Slice
The instruction Slice
slices the slice or the string addressed by s1
and stores the resulting slice or string into s2
. The values addressed by low
, high
and max
are the low, high and max indices. max
is optional for slices and it is never present for strings.
Syntax: Slice s1 low high s2 ; description: s2 = s1[low:high]
Slice s1 low high max s2 ; s2 = s1[low:high:max]
Sub
The instruction Sub
subtracts two integers or two floats. Sub
has two forms.
The first form subtracts the operands addressed by b
from the operand addressed by a
and stores the result in c
, the type of operands is int
or float64
.
The second form subtracts the operand addressed by b
from the operand addressed by c
and stores the result in c
. type
is the type of the operands.
b
can be an integer constant between 0 and 255.
Syntax: Sub a b c ; description: c = a - b // int and float64 types
Sub type b c ; description: c -= b
Example: Sub i3 i9 i2
Sub f8 23 f2
Sub int64 i7 i1
Sub float64 f14 f21
SubInv
The instruction SubInv
subtracts two integers or two floats. SubInv
has two forms.
The first form subtracts the operand addressed by a
from the operand addressed by b
and stores the result in c
, the type of operands is int
or float64
.
The second form subtracts the constant addressed by b
from the operand addressed by c
and stores the result in c
. type
is the type of the operands.
The operand b
is an integer constant between -128 and 127.
Syntax: SubInv a b c ; description: c = b - a // int and float64 types
SubInv type b c ; description: c = b - c
Example: SubInv i3 i9 i2
SubInv f8 -23 f2
SubInv int64 i7 i1
SubInv float64 f14 f21
TailCall
TODO
Text
The instruction Text
writes the text txt
to the template out writer.
Syntax: Text txt ; description: out.Write(txt)
Example: Text "<h1>About us</h1>"
Typify
The instruction Typify
gets the value addressed by v1
, convert it to type T
and stores the resulting value into v2
.
Syntax: Typify T v1 v2 ; description: var v2 T = v1
Xor
The instruction Xor
computes the bitwise XOR of the operands addressed by a
and b
and stores the result in c
.
Syntax: Xor a b c ; description: c = a ^ b
Zero
The instruction Zero
checks if the value addressed by the register b
is a zero value; if so, then stores 1
in the integer register c
, otherwise stores 0
.
As special cases, if the value addressed by b
is an empty slice or an empty
channel the instruction Zero
stores 1
.
Moreover, if the value addressed by b
has type interface and it is not nil
,
the instruction Zero
evaluates its dynamic value.
Syntax: Zero b c ; description: c = 1 if b is the zero value for its type
c = 0 otherwise
Example: Zero i1 i2
Zero s1 i3
See also the NotZero instruction.