bom

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package bom rolls up a bill of materials by tail recursion, as a state machine. A part has a value, its own cost, and lines, each a quantity of another part. The cost of one part is its value plus, for each line, the quantity times the cost of that part, and the number of each part a system needs is the quantities multiplied down every path to it, summed.

That recursion is not a tail call: a part calls itself once per line. Passing the work still to do as an argument, a stack, makes it one:

walk(stack, need, subtotal) = need, subtotal         if stack is empty
walk(stack, need, subtotal) = walk(stack', need', subtotal')

where stack', need' and subtotal' are what visiting the top entry makes of them. Going down to a part, the system needs times more of it, and the entry becomes one to come back to the part, with an entry for each line pushed above it. Coming back, every line's part has its subtotal, so the part's is its value plus theirs, and the entry is popped.

The machine is the call: it holds the bill and all three arguments, and each EvCall evaluates it once. A tail call replaces the arguments, so the machine is the next call and nothing is left to return to. The holder's loop is the trampoline: it fires until the call has returned.

The machine refuses a part that contains itself, numbers that would not fit in 64 bits, and more calls than the limit New is given.

Index

Constants

View Source
const (
	MaxParts = 16 // parts in a bill
	MaxLines = 8  // lines in a part
)

The size of a bill the machine holds.

View Source
const MaxStack = MaxParts * (MaxLines + 1)

MaxStack is the most entries the stack holds. Every entry on it is the way back to a part on the current path, or a line of one, and a part is on the path at most once, so an acyclic bill never needs more.

Variables

This section is empty.

Functions

This section is empty.

Types

type Event

type Event uint8

Event is an input to Fire.

const (
	EvCall Event // evaluate walk(stack, need, subtotal) once

)

Event values.

type Line

type Line struct {
	Part     int64 // the part, an index into the bill
	Quantity int64 // how many, at least one
}

Line is a quantity of one part in another.

type Machine

type Machine struct {
	// contains filtered or unexported fields
}

Machine is the call walk(stack, need, subtotal) on one bill. Build it with New and change it only with Fire.

func New

func New(parts []Part, top, calls int64) Machine

New returns the call walk([top], 0, 0) on the bill parts, making at most calls tail calls. A bill of no parts or more than MaxParts, a part of more than MaxLines lines, a negative value, a line to a part not in the bill or of a quantity below one, or a limit below one gives a walk in BadInput.

func (Machine) Calls

func (m Machine) Calls() int64

Calls returns how many tail calls the walk has made.

func (Machine) Fire

func (m Machine) Fire(e Event) (Machine, fsm.Outcome)

Fire applies e.

func (Machine) Need

func (m Machine) Need(p int64) (int64, bool)

Need returns how many of part p one system needs, as far as the walk has gone, or false when p is not in the bill.

func (Machine) Size

func (m Machine) Size() int64

Size returns how many entries are on the stack.

func (Machine) State

func (m Machine) State() State

State returns the control state.

func (Machine) Subtotal

func (m Machine) Subtotal(p int64) (int64, bool)

Subtotal returns the cost of one of part p, or false when p is not in the bill or the walk has not yet come back to it.

type Part

type Part struct {
	Value int64 // at least zero
	Lines []Line
}

Part is a part or an assembly. Its value is its own cost, such as the labour to assemble it.

type State

type State uint8

State is the walk's control state.

const (
	Calling  State // walk(stack, need, subtotal) is being evaluated
	Returned       // the stack is empty: the walk returned
	Cyclic         // a part is on the path to itself
	TooLarge       // a number would not fit in 64 bits, or the calls passed their limit
	BadInput       // New was given a bill or limit it does not accept

)

State values.

func (State) String

func (s State) String() string

Directories

Path Synopsis
Package rollup is the holder for package bom.
Package rollup is the holder for package bom.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL