PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/x/vm/bf/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / x / vm / bf
Files
9 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/x/vm/bf/v0
gno
0.9

Files (9)

  • README.mdmarkdown
  • gnomod.tomltoml
  • bf.gnogno
  • compile.gnogno
  • machine.gnogno
  • bf_test.gnogno
  • ladder_test.gnogno
  • machine_test.gnogno
  • micro_test.gnogno
  • bf.gnogno
    1// Package bf is a Brainfuck machine for gno.land, and the measuring stick the2// rest of the guest-VM work is calibrated against.3//4// It ships two things that look alike and are not:5//6//   - [Execute], the naive interpreter: a switch over the source bytes, a7//     brace matcher that rescans the program on every loop edge. It is kept

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    8// verbatim as rung 0 of the optimization ladder, because a baseline you
    9// have edited is not a baseline.
    10// - [Compile] plus [Machine], the real one: the program is compiled to an
    11// op array with resolved jumps, runs of identical operators are fused,
    12// the common loop idioms become single ops, and execution is metered by
    13// a caller-supplied fuel budget against a
    14// [vmkit](/p/moul/x/vm/vmkit/v0) Host, so a program can pause when it
    15// runs out and resume in a later transaction.
    16//
    17// The ladder between them is measured, not asserted: see the README for the
    18// table, and ladder_test.gno for the harness that produces it.
    19//
    20// Live demo: [r/moul/x/vm/bfdemo](/r/moul/x/vm/bfdemo/v0).
    21package bf
    22
    23import "strings"
    24
    25// NaiveTapeSize is the tape length used by [Execute]. It is 30,000 because
    26// that is what the original had, and rung 0 is not allowed to drift.
    27const NaiveTapeSize = 30000
    28
    29// Execute runs code on a fresh tape and returns everything it wrote, using
    30// the original 2023 implementation: no compilation step, one switch per
    31// source byte, and a brace matcher that rescans the source every time a loop
    32// opens or closes.
    33//
    34// It is rung 0 of the ladder and exists to be measured. Two of its properties
    35// are bugs that are deliberately preserved, and are the reason nothing should
    36// call it on untrusted input:
    37//
    38// - `,` panics with "unsupported": there is no input.
    39// - unbalanced brackets run the scan off the end of the source and panic
    40// with an index out of range.
    41//
    42// Use [Compile] and [Machine] for anything real: they reject a malformed
    43// program up front, read input from the host, and cannot run unbounded.
    44func Execute(code string) string {
    45 var (
    46 memory = make([]byte, NaiveTapeSize) // memory tape
    47 pointer = 0 // initial memory pointer
    48 buf strings.Builder
    49 )
    50
    51 // Loop through each character in the code
    52 for i := 0; i < len(code); i++ {
    53 switch code[i] {
    54 case '>':
    55 // Increment memory pointer
    56 pointer++
    57 if pointer >= NaiveTapeSize {
    58 pointer = 0
    59 }
    60 case '<':
    61 // Decrement memory pointer
    62 pointer--
    63 if pointer < 0 {
    64 pointer = NaiveTapeSize - 1
    65 }
    66 case '+':
    67 // Increment the byte at the memory pointer
    68 memory[pointer]++
    69 case '-':
    70 // Decrement the byte at the memory pointer
    71 memory[pointer]--
    72 case '.':
    73 // Output the byte at the memory pointer
    74 buf.WriteByte(memory[pointer])
    75 case ',':
    76 // Input a byte and store it in the memory
    77 panic("unsupported")
    78 case '[':
    79 // Jump forward past the matching ']' if the byte at the memory pointer is zero
    80 if memory[pointer] == 0 {
    81 braceCount := 1
    82 for braceCount > 0 {
    83 i++
    84 if code[i] == '[' {
    85 braceCount++
    86 } else if code[i] == ']' {
    87 braceCount--
    88 }
    89 }
    90 }
    91 case ']':
    92 // Jump backward to the matching '[' if the byte at the memory pointer is nonzero
    93 if memory[pointer] != 0 {
    94 braceCount := 1
    95 for braceCount > 0 {
    96 i--
    97 if code[i] == ']' {
    98 braceCount++
    99 } else if code[i] == '[' {
    100 braceCount--
    101 }
    102 }
    103 i-- // Move back one more to compensate for the upcoming increment in the loop
    104 }
    105 }
    106 }
    107 return buf.String()
    108}
    109