go¶
The Go target, go, generates a Go module of one package binding the API
through cgo, into <output>/go:
go.modThe module, named as the prefix,
foo, and needing Go 1.22.<prefix>.goThe bindings, in two layers.
<prefix>_link.goWhat links the library,
-l<name>, the name of the API withoutlib. Built with the tag<prefix>_no_link, the package links nothing, for what uses only its types.<prefix>_no_link.cWhat the tag links in place of the library: each function by its name only, aborting when called, as cgo refers to every function the package calls.
<prefix>_callbacks.cThe C trampolines of the callbacks given as Go functions, when there are any.
lib<prefix>.hThe C API, as the C target emits it, which the package includes.
check/main.goThe check, not part of the API: it does not compile unless every record has the size, alignment and field offsets recorded in the IR, then prints a zeroed instance of every record, as YAML or JSON.
The package needs cgo, and so a C compiler. yace vets the package and the
check, with $GO, by default go, and the tag <prefix>_no_link, so the
library need not be built, then builds and runs the check, and parses what it
printed, as YAML and as JSON. As for the C API, the layout is asserted only on
the platform it was recorded on.
A program uses the package by requiring the module, with a replace
directive giving where it was generated, and links the library found through
CGO_LDFLAGS, such as -L/path/to/lib. Headers the API includes are found
through CGO_CFLAGS.
The raw layer¶
The C API as C has it, by its C names, which Go exports only from an upper-case
letter: foo_open() is Foo_open(), FOO_MAGIC stays FOO_MAGIC.
Each function converts what it is given and calls the C function through cgo.
cgo’s own types are of no use outside the package, so the records are Go structs
of the C layout, named in CamelCase, struct foo_point as FooPoint, with
their fields exported, Ncorners; the layout is what the check asserts.
A union is its bytes, aligned as the union, and a method per member returning a
pointer to the member in them, *value.I() = -1, as Go has no unions. A
record with bit-fields keeps only its size and alignment, as in Zig. A packed
record, which cgo does not declare the unaligned fields of, is its bytes, with
a getter and a setter per field reading and writing a copy of it, At() and
SetAt(value), as Go aligns every field. A getter, also of a part of a
field of bits, takes the record by value, so getters chain, Many()[1].At();
the garbage collector does not see
a pointer set through a setter. A flexible
array, last in a struct, is left out, as a struct ending in a zero-sized field
is padded in Go; a comment says so. An opaque record is a struct of no fields,
usable only through pointers, as is a type declared outside the headers.
Pointers are Go pointers, which may point to C memory; void * and function
pointers are unsafe.Pointer, and a callback typedef a type of its own over
it. C’s long and unsigned long are CLong and CULong, as wide as
the platform’s; size_t and uintptr_t are uintptr, ssize_t,
ptrdiff_t and intptr_t are int. Each enum is an integer type, not a
closed set, its members constants by their C names, with Name() the C name
of a value and whether it has one, and String() the name or the type and the
value.
What cgo cannot call is not bound, and a comment in its place says why: a variadic function, one named as a Go keyword, or one taking or returning by value a type Go knows only the name of.
Every struct and union has printers of its own, not calling the C API’s:
Fpr(w, flags) prints to an io.Writer, also through a nil pointer, as
<name>_fpr() does, and String(), the fmt.Stringer of the record, is
its YAML. They print what the C API’s pretty-printers print, floats as C’s
%g prints them, except for a record with bit-fields: Go keeps it as its
bytes, so it has no printers, and a record holding one prints it as null,
where the C printers print its fields. Each part of
a field of bits, see The C Subset, has a getter and a setter,
CodeType() and SetCodeType(value), of the field’s type, the setter
panicking on a value that does not fit the part’s bits. A name the struct has
already, as a field or a printer, gets a trailing underscore.
Memory given to C must hold no Go pointers, as cgo requires: a record given by a pointer may point to C memory, not to Go memory. cgo checks it as it passes the record.
The idiomatic layer¶
Over the raw one, from what the header says beyond C, see
The C Subset, and as derived in yace.targets.idiom. Its
functions are named in CamelCase, without the prefix:
- Handles
An opaque record is a struct holding the pointer, named without the prefix:
struct foo_handleisHandle. Its constructor is a function of the package,foo.Open(), returning a*Handle, nil where it has no@errnoand C gave none; its destructor is a method,Close(), fordefer handle.Close(); the functions taking it first are its methods.Ptr()is the raw pointer. A handle given otherwise is a*of its struct, nil passing NULL.- Errors
A function documented
@errnoreturns anerrorlast, asyscall.Errnowrapped with the name of the C function, soerrors.Is(err, syscall.EINVAL)holds for-EINVAL. One returningintreturns only theerror; one returning another integer, such as a count, anintbefore it.- Results
What a function writes through an
[out]pointer is returned rather than passed. An[out]array is written to a slice the caller gives, asio.Readerdoes, and the part written is returned. A returned string is a Gostring, copied. A returned pointer to a record is a copy of it, with whether there was one where@nullable,point, ok := handle.PointGet(1).- Arguments
A string is a
string, a*stringwhere@nullable, nil passing NULL; it is copied to C memory for the call, up to its first NUL. An array read through a pointer is a slice; slices sharing one@lencount must be as long, or the call panics; a nil slice passes NULL. Avoid *with a@lenis a[]byte.- Callbacks
A callback is a Go function, of a type named for the callback typedef,
FooVisitCbFunc, without thevoid *context, its pointers to records Go pointers to C memory valid during the call, its strings copied. cgo lets C hold no Go pointer, so the function is kept in aruntime/cgo.Handle, held in C memory given as the context, which a C trampoline gives to the Go function the package exports for the callback. It is released as its@lifetimesays (see Callback lifetimes): when the call returns, forcall; once it has been called, foronce; when the handle is destroyed, forhandle, and never where the destructor fails or nothing destroys the handle, as C may still hold it. One the call fails to take, by its@errno, is released at once. A@nullablecallback may be nil, passing NULL. A panic in the function unwinds the C frames that called it, which C does not expect.
A call that has no idiomatic form, as the raw layer does not bind it or what it
writes has no fields to return, has a comment in its place naming the raw
function. A name that is a Go keyword or a predeclared identifier, such as
len, a package the code uses, such as unsafe, a name of the package, or
a local of the layer, such as ret, gets a trailing underscore as a
parameter, as does a function named as one before it in the package, or a
method named Ptr.
Example¶
yace output/foo.yaml --emit go --output output
output/go
├── check
│ └── main.go
├── check.json
├── check.yaml
├── foo.go
├── foo_callbacks.c
├── foo_check
├── foo_link.go
├── foo_no_link.c
├── go.log
├── go.mod
└── libfoo.h
2 directories, 11 files
The fixture library is called through the idiomatic layer, and the raw one for
what the idiomatic one does not take, by
examples/libfoo/checks/go/main.go:
// The check of the Go bindings of libfoo: calls the library through the
// idiomatic layer, its handle, errors and returned values, and prints what it
// got back, as YAML documents, or with argument "json" as JSON objects, each
// holding what 'expected.yaml' says. An error is printed as the negative errno
// the C function returned; what the layer does not take, a NULL where none is
// allowed or a callback of C, is called raw.
package main
/*
#include <stdint.h>
#include <stdlib.h>
extern int addX(void *arg, void *point);
*/
import "C"
import (
"errors"
"fmt"
"io"
"os"
"strings"
"syscall"
"unsafe"
"foo"
)
var asJSON = false
type field struct {
key string
value string // as JSON, which is also YAML
}
func num[T ~int | ~int32 | ~int64 | ~uint16 | ~uintptr](value T) string {
return fmt.Sprint(value)
}
func quoted(text string) string {
return `"` + text + `"`
}
func document(name string, fields []field) {
if asJSON {
parts := make([]string, len(fields))
for idx, f := range fields {
parts[idx] = quoted(f.key) + ": " + f.value
}
fmt.Printf("{%s: {%s}}\n", quoted(name), strings.Join(parts, ", "))
return
}
fmt.Printf("---\n%s:\n", name)
for _, f := range fields {
fmt.Printf(" %s: %s\n", f.key, f.value)
}
}
// record prints a record, or nil, with the printer the bindings give it
func record(name string, fpr func(w io.Writer, flags int) error) {
flags := foo.FOO_PR_YAML
if asJSON {
flags = foo.FOO_PR_JSON
fmt.Printf("{%s: ", quoted(name))
} else {
fmt.Println("---")
}
if err := fpr(os.Stdout, flags); err != nil {
panic(err)
}
if asJSON {
fmt.Println("}")
}
}
// errno is the negative errno of err, 0 for none
func errno(err error) int64 {
var found syscall.Errno
if errors.As(err, &found) {
return -int64(found)
}
if err != nil {
panic(err)
}
return 0
}
// value is 'value', or the negative errno of err
func value[T ~int | ~uintptr](value T, err error) int64 {
if err != nil {
return errno(err)
}
return int64(value)
}
type shape interface{ Name() (string, bool) }
func names[T shape](values ...T) string {
found := make([]string, len(values))
for idx, v := range values {
name, ok := v.Name()
if !ok {
name = "UNKNOWN"
}
found[idx] = quoted(name)
}
return "[" + strings.Join(found, ", ") + "]"
}
//export addX
func addX(arg unsafe.Pointer, point unsafe.Pointer) C.int {
*(*int64)(arg) += int64((*foo.FooPoint)(point).X)
return 0
}
func main() {
asJSON = len(os.Args) > 1 && os.Args[1] == "json"
document("defines", []field{
{"FOO_NAME", quoted(foo.FOO_NAME)},
{"FOO_MAGIC", num(foo.FOO_MAGIC)},
{"FOO_VERSION_MAJOR", num(foo.FOO_VERSION_MAJOR)},
{"FOO_VERSION_MINOR", num(foo.FOO_VERSION_MINOR)},
{"FOO_VERSION_PATCH", num(foo.FOO_VERSION_PATCH)},
{"FOO_POINTS_MAX", num(foo.FOO_POINTS_MAX)},
{"FOO_DEFAULT_SHAPE_SIDES", num(foo.FOO_DEFAULT_SHAPE_SIDES)},
})
document("enums", []field{
{"foo_shape", names[foo.FooShape](-1, 0, 1, 2, 3)},
{"foo_option", names[foo.FooOption](1, 2, 3)},
})
points := []foo.FooPoint{{X: 1, Y: 2}, {X: 3, Y: 4}, {X: 5, Y: 6}}
handle, err := foo.Open("points")
if err != nil {
panic(err)
}
defer handle.Close()
var unopened *foo.FooHandle
openWithoutName := foo.Foo_open(nil, &unopened)
var watched, watchedX int64
watch := errno(handle.PointWatch(func(point *foo.FooPoint) {
watched++
watchedX += int64(point.X)
}))
watchBusy := errno(handle.PointWatch(func(point *foo.FooPoint) {}))
added := 0
for idx := range points {
if handle.PointAdd(&points[idx]) == nil {
added++
}
}
count := handle.PointCount()
var sumX, sumY int64
visit := value(handle.PointVisit(func(point *foo.FooPoint) int32 {
sumX += int64(point.X)
sumY += int64(point.Y)
return 0
}))
visited := 0
stopped := value(handle.PointVisit(func(point *foo.FooPoint) int32 {
visited++
if visited == 2 {
return 1
}
return 0
}))
without := foo.Foo_point_visit(handle.Ptr(), nil, nil)
withX := (*int64)(C.malloc(C.size_t(unsafe.Sizeof(int64(0)))))
defer C.free(unsafe.Pointer(withX))
*withX = 0
visitor := foo.FooVisitor{Visit: foo.FooVisitCb(C.addX), Arg: unsafe.Pointer(withX)}
visitWith := value(handle.PointVisitWith(&visitor))
_, err = foo.FigureFill(3)
unknown := errno(err)
addMany := value(handle.PointAddMany(points))
countAfter := handle.PointCount()
watchedAfter, watchedXAfter := watched, watchedX
copied, err := handle.PointCopy(make([]foo.FooPoint, 4))
if err != nil {
panic(err)
}
var copiedX int64
for _, p := range copied {
copiedX += int64(p.X)
}
var done uintptr
submit := errno(handle.CountSubmit(func(count uintptr) { done = count }))
submitBusy := errno(handle.CountSubmit(func(count uintptr) { done = 0 }))
complete := handle.CountComplete()
completeAgain := handle.CountComplete()
document("calls", []field{
{"version", quoted(foo.Version())},
{"open", "0"},
{"open_without_name", num(openWithoutName)},
{"name", quoted(handle.Name())},
{"watch", num(watch)},
{"watch_busy", num(watchBusy)},
{"added", num(added)},
{"count", num(count)},
{"visit", num(visit)},
{"visit_sum_x", num(sumX)},
{"visit_sum_y", num(sumY)},
{"visit_stopped", num(stopped)},
{"visit_without_callback", num(without)},
{"visit_with", num(visitWith)},
{"visit_with_sum_x", num(*withX)},
{"figure_of_unknown_shape", num(unknown)},
{"add_many", num(addMany)},
{"count_after_add_many", num(countAfter)},
{"watched", num(watchedAfter)},
{"watched_sum_x", num(watchedXAfter)},
{"points_copied", num(len(copied))},
{"points_sum_x", num(copiedX)},
{"submit", num(submit)},
{"submit_busy", num(submitBusy)},
{"complete", num(complete)},
{"done_count", num(done)},
{"complete_again", num(completeAgain)},
})
for _, idx := range []uintptr{1, 6} {
point, ok := handle.PointGet(idx)
if !ok {
record("foo_point", (*foo.FooPoint)(nil).Fpr)
continue
}
record("foo_point", point.Fpr)
}
for handle.PointAdd(&points[0]) == nil {
}
document("full", []field{
{"count", num(handle.PointCount())},
{"add", num(errno(handle.PointAdd(&points[0])))},
{"add_many", num(value(handle.PointAddMany(points[:1])))},
{"watched", num(watched)},
})
status := handle.StatusGet()
record("foo_status", status.Fpr)
document("status", []field{
{"pending", num(status.CodePending())},
{"points", num(status.CodePoints())},
{"full", num(status.CodeFull())},
})
made := foo.FooStatus{Code: 0, Max: foo.FOO_POINTS_MAX}
made.SetCodePoints(5)
made.SetCodePending(1)
record("foo_status", made.Fpr)
scalars := foo.ScalarsFill()
record("foo_scalars", scalars.Fpr)
for _, shape := range []foo.FooShape{foo.FOO_SHAPE_POINT, foo.FOO_SHAPE_LINE, foo.FOO_SHAPE_POLYGON} {
figure, err := foo.FigureFill(uint32(shape))
if err != nil {
panic(err)
}
record("foo_figure", figure.Fpr)
}
set := foo.ValueSet(-1)
record("foo_value", set.Fpr)
wire := foo.WireFill()
record("foo_wire", wire.Fpr)
}
Bindings¶
// Code generated by yace from foo.h; DO NOT EDIT.
// SPDX-License-Identifier: GPL-2.0-only
// Package foo binds libfoo: An example library described in the C subset of yace
//
// The raw layer declares the C API as C has it, by its C names, exported; the
// idiomatic layer, after it, is what the header says beyond C. Every struct and
// union prints itself as the C API's pretty-printers print it. Memory given to
// C must hold no Go pointers, as cgo requires.
package foo
/*
#cgo CFLAGS: -I${SRCDIR}
#include <stdlib.h>
#include "libfoo.h"
void yace_foo_added_cb(void *a0, const struct foo_point *a1);
int yace_foo_visit_cb(void *a0, const struct foo_point *a1);
void yace_foo_done_cb(void *a0, size_t a1);
*/
import "C"
import (
"errors"
"fmt"
"io"
"math"
"runtime/cgo"
"strconv"
"syscall"
"unsafe"
)
// CLong is C's long, as wide as the platform's
type CLong = C.long
// CULong is C's unsigned long, as wide as the platform's
type CULong = C.ulong
// The output formats of the pretty-printers
const (
// The default, YAML
FOO_PR_DEF = 0x0
// YAML
FOO_PR_YAML = 0x1
// Terse; the generated printers print YAML
FOO_PR_TERSE = 0x2
// JSON, on one line
FOO_PR_JSON = 0x4
)
// yaceIndent appends indent spaces to out
func yaceIndent(out []byte, indent int) []byte {
for ; indent > 0; indent-- {
out = append(out, ' ')
}
return out
}
func yaceBool(out []byte, value bool) []byte {
if value {
return append(out, "true"...)
}
return append(out, "false"...)
}
// yaceG appends value as C's printf() prints it with "%g"
func yaceG(out []byte, value float64) []byte {
switch {
case math.IsNaN(value) && math.Signbit(value):
return append(out, "-nan"...)
case math.IsNaN(value):
return append(out, "nan"...)
case math.IsInf(value, 1):
return append(out, "inf"...)
case math.IsInf(value, -1):
return append(out, "-inf"...)
}
return strconv.AppendFloat(out, value, 'g', 6, 64)
}
// yaceStrn appends chars, up to the first NUL, as a JSON string
func yaceStrn(out []byte, chars []byte) []byte {
const hex = "0123456789abcdef"
out = append(out, '"')
for _, chr := range chars {
switch {
case chr == 0:
return append(out, '"')
case chr == '"' || chr == '\\':
out = append(out, '\\', chr)
case chr < 0x20 || chr == 0x7f:
out = append(out, '\\', 'u', '0', '0', hex[chr>>4], hex[chr&0xf])
default:
out = append(out, chr)
}
}
return append(out, '"')
}
// yaceStr appends the C string at ptr as a JSON string, or null
func yaceStr(out []byte, ptr unsafe.Pointer) []byte {
if ptr == nil {
return append(out, "null"...)
}
return yaceStrn(out, []byte(C.GoString((*C.char)(ptr))))
}
// yaceGet reads a T from the start of b, which need not be aligned for it
func yaceGet[T any](b []byte) T {
var v T
copy(unsafe.Slice((*byte)(unsafe.Pointer(&v)), unsafe.Sizeof(v)), b)
return v
}
// yaceSet writes v to the start of b, which need not be aligned for it
func yaceSet[T any](b []byte, v T) {
copy(b, unsafe.Slice((*byte)(unsafe.Pointer(&v)), unsafe.Sizeof(v)))
}
// yacePtr appends addr in hexadecimal, as a string, or null
func yacePtr(out []byte, addr uintptr) []byte {
if addr == 0 {
return append(out, "null"...)
}
out = strconv.AppendUint(append(out, `"0x`...), uint64(addr), 16)
return append(out, '"')
}
// Name of the library
const FOO_NAME = "foo"
// A hexadecimal constant
const FOO_MAGIC = 0xacdc
// Major version
const FOO_VERSION_MAJOR = 1
// Minor version
const FOO_VERSION_MINOR = 2
// Patch version
const FOO_VERSION_PATCH = 3
// Points a handle holds at most
const FOO_POINTS_MAX = 8
// A constant, by name
const FOO_DEFAULT_SHAPE_SIDES = 8
// A count is submitted and not yet completed; bit 0 of 'code'
const FOO_STATUS_CODE_PENDING = 0x1
// Points held; bits 11:4 of 'code'
const FOO_STATUS_CODE_POINTS = 0xff0
// The handle holds FOO_POINTS_MAX points; bit 15 of 'code'
const FOO_STATUS_CODE_FULL = 0x8000
// Kinds of figure
//
// An integer, not a closed set: C does not restrict an enum to the
// values it names.
type FooShape int32
const (
// No figure
FOO_SHAPE_NONE FooShape = -1
// A single point
FOO_SHAPE_POINT FooShape = 0
// Two points
FOO_SHAPE_LINE FooShape = 1
// Three points or more
FOO_SHAPE_POLYGON FooShape = 2
)
// Name is the C name of the value, and whether it has one
func (v FooShape) Name() (string, bool) {
switch v {
case FOO_SHAPE_NONE:
return "FOO_SHAPE_NONE", true
case FOO_SHAPE_POINT:
return "FOO_SHAPE_POINT", true
case FOO_SHAPE_LINE:
return "FOO_SHAPE_LINE", true
case FOO_SHAPE_POLYGON:
return "FOO_SHAPE_POLYGON", true
}
return "", false
}
// String is the C name of the value, or FooShape(<value>) for one
// not named
func (v FooShape) String() string {
if name, ok := v.Name(); ok {
return name
}
return "FooShape(" + strconv.FormatInt(int64(v), 10) + ")"
}
// Options of a figure, combined as bits
//
// An integer, not a closed set: C does not restrict an enum to the
// values it names.
type FooOption uint32
const (
// The last corner connects to the first
FOO_OPTION_CLOSED FooOption = 1
// The inside is filled
FOO_OPTION_FILLED FooOption = 2
)
// Name is the C name of the value, and whether it has one
func (v FooOption) Name() (string, bool) {
switch v {
case FOO_OPTION_CLOSED:
return "FOO_OPTION_CLOSED", true
case FOO_OPTION_FILLED:
return "FOO_OPTION_FILLED", true
}
return "", false
}
// String is the C name of the value, or FooOption(<value>) for one
// not named
func (v FooOption) String() string {
if name, ok := v.Name(); ok {
return name
}
return "FooOption(" + strconv.FormatUint(uint64(v), 10) + ")"
}
// A collection of points, opened with foo_open() and closed with foo_close()
type FooHandle struct{ _ [0]byte }
// A point on the plane
type FooPoint struct {
// Horizontal position
X int32
// Vertical position
Y int32
}
func (r *FooPoint) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"x\": "...)
out = strconv.AppendInt(out, int64(r.X), 10)
out = append(out, ", \"y\": "...)
out = strconv.AppendInt(out, int64(r.Y), 10)
return append(out, '}')
}
func (r *FooPoint) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "x: "...)
out = strconv.AppendInt(out, int64(r.X), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "y: "...)
out = strconv.AppendInt(out, int64(r.Y), 10)
out = append(out, '\n')
return out
}
// Fpr prints r, or null when nil, to w, as foo_point_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooPoint) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_point: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_point:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooPoint) String() string {
return string(r.yaceYAML([]byte("foo_point:\n"), 2))
}
// A callback and its argument
type FooVisitor struct {
// Called for each point
Visit FooVisitCb
// Given to 'visit'
Arg unsafe.Pointer
}
func (r *FooVisitor) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"visit\": "...)
out = yacePtr(out, uintptr(unsafe.Pointer(r.Visit)))
out = append(out, ", \"arg\": "...)
out = yacePtr(out, uintptr(unsafe.Pointer(r.Arg)))
return append(out, '}')
}
func (r *FooVisitor) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "visit: "...)
out = yacePtr(out, uintptr(unsafe.Pointer(r.Visit)))
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "arg: "...)
out = yacePtr(out, uintptr(unsafe.Pointer(r.Arg)))
out = append(out, '\n')
return out
}
// Fpr prints r, or null when nil, to w, as foo_visitor_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooVisitor) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_visitor: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_visitor:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooVisitor) String() string {
return string(r.yaceYAML([]byte("foo_visitor:\n"), 2))
}
// A value of every kind of scalar
type FooScalars struct {
// bool
Flag bool
// char
Letter byte
// signed char
Schar int8
// unsigned char
Uchar uint8
// short
S int16
// unsigned short
Us uint16
// int
I int32
// unsigned int
Ui uint32
// long
L CLong
// unsigned long
Ul CULong
// long long
Ll int64
// unsigned long long
Ull uint64
// float
F float32
// double
D float64
// int8_t
I8 int8
// int16_t
I16 int16
// int32_t
I32 int32
// int64_t
I64 int64
// uint8_t
U8 uint8
// uint16_t
U16 uint16
// uint32_t
U32 uint32
// uint64_t
U64 uint64
// intptr_t
Iptr int
// uintptr_t
Uptr uintptr
// size_t
Size uintptr
// ssize_t
Ssize int
// ptrdiff_t
Diff int
}
func (r *FooScalars) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"flag\": "...)
out = yaceBool(out, r.Flag)
out = append(out, ", \"letter\": "...)
out = strconv.AppendInt(out, int64(C.char(r.Letter)), 10)
out = append(out, ", \"schar\": "...)
out = strconv.AppendInt(out, int64(r.Schar), 10)
out = append(out, ", \"uchar\": "...)
out = strconv.AppendUint(out, uint64(r.Uchar), 10)
out = append(out, ", \"s\": "...)
out = strconv.AppendInt(out, int64(r.S), 10)
out = append(out, ", \"us\": "...)
out = strconv.AppendUint(out, uint64(r.Us), 10)
out = append(out, ", \"i\": "...)
out = strconv.AppendInt(out, int64(r.I), 10)
out = append(out, ", \"ui\": "...)
out = strconv.AppendUint(out, uint64(r.Ui), 10)
out = append(out, ", \"l\": "...)
out = strconv.AppendInt(out, int64(r.L), 10)
out = append(out, ", \"ul\": "...)
out = strconv.AppendUint(out, uint64(r.Ul), 10)
out = append(out, ", \"ll\": "...)
out = strconv.AppendInt(out, int64(r.Ll), 10)
out = append(out, ", \"ull\": "...)
out = strconv.AppendUint(out, uint64(r.Ull), 10)
out = append(out, ", \"f\": "...)
out = yaceG(out, float64(r.F))
out = append(out, ", \"d\": "...)
out = yaceG(out, float64(r.D))
out = append(out, ", \"i8\": "...)
out = strconv.AppendInt(out, int64(r.I8), 10)
out = append(out, ", \"i16\": "...)
out = strconv.AppendInt(out, int64(r.I16), 10)
out = append(out, ", \"i32\": "...)
out = strconv.AppendInt(out, int64(r.I32), 10)
out = append(out, ", \"i64\": "...)
out = strconv.AppendInt(out, int64(r.I64), 10)
out = append(out, ", \"u8\": "...)
out = strconv.AppendUint(out, uint64(r.U8), 10)
out = append(out, ", \"u16\": "...)
out = strconv.AppendUint(out, uint64(r.U16), 10)
out = append(out, ", \"u32\": "...)
out = strconv.AppendUint(out, uint64(r.U32), 10)
out = append(out, ", \"u64\": "...)
out = strconv.AppendUint(out, uint64(r.U64), 10)
out = append(out, ", \"iptr\": "...)
out = strconv.AppendInt(out, int64(r.Iptr), 10)
out = append(out, ", \"uptr\": "...)
out = strconv.AppendUint(out, uint64(r.Uptr), 10)
out = append(out, ", \"size\": "...)
out = strconv.AppendUint(out, uint64(r.Size), 10)
out = append(out, ", \"ssize\": "...)
out = strconv.AppendInt(out, int64(r.Ssize), 10)
out = append(out, ", \"diff\": "...)
out = strconv.AppendInt(out, int64(r.Diff), 10)
return append(out, '}')
}
func (r *FooScalars) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "flag: "...)
out = yaceBool(out, r.Flag)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "letter: "...)
out = strconv.AppendInt(out, int64(C.char(r.Letter)), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "schar: "...)
out = strconv.AppendInt(out, int64(r.Schar), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "uchar: "...)
out = strconv.AppendUint(out, uint64(r.Uchar), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "s: "...)
out = strconv.AppendInt(out, int64(r.S), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "us: "...)
out = strconv.AppendUint(out, uint64(r.Us), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "i: "...)
out = strconv.AppendInt(out, int64(r.I), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "ui: "...)
out = strconv.AppendUint(out, uint64(r.Ui), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "l: "...)
out = strconv.AppendInt(out, int64(r.L), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "ul: "...)
out = strconv.AppendUint(out, uint64(r.Ul), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "ll: "...)
out = strconv.AppendInt(out, int64(r.Ll), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "ull: "...)
out = strconv.AppendUint(out, uint64(r.Ull), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "f: "...)
out = yaceG(out, float64(r.F))
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "d: "...)
out = yaceG(out, float64(r.D))
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "i8: "...)
out = strconv.AppendInt(out, int64(r.I8), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "i16: "...)
out = strconv.AppendInt(out, int64(r.I16), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "i32: "...)
out = strconv.AppendInt(out, int64(r.I32), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "i64: "...)
out = strconv.AppendInt(out, int64(r.I64), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "u8: "...)
out = strconv.AppendUint(out, uint64(r.U8), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "u16: "...)
out = strconv.AppendUint(out, uint64(r.U16), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "u32: "...)
out = strconv.AppendUint(out, uint64(r.U32), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "u64: "...)
out = strconv.AppendUint(out, uint64(r.U64), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "iptr: "...)
out = strconv.AppendInt(out, int64(r.Iptr), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "uptr: "...)
out = strconv.AppendUint(out, uint64(r.Uptr), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "size: "...)
out = strconv.AppendUint(out, uint64(r.Size), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "ssize: "...)
out = strconv.AppendInt(out, int64(r.Ssize), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "diff: "...)
out = strconv.AppendInt(out, int64(r.Diff), 10)
out = append(out, '\n')
return out
}
// Fpr prints r, or null when nil, to w, as foo_scalars_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooScalars) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_scalars: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_scalars:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooScalars) String() string {
return string(r.yaceYAML([]byte("foo_scalars:\n"), 2))
}
// A figure: its kind, where it is, and its corners
type FooFigure struct {
// One of enum foo_shape
Shape uint32
// Bits of enum foo_option
Options uint32
// Where the figure is
Origin FooPoint
// The corners, relative to 'origin'
Corners [4]FooPoint
// How many of 'corners' are used
Ncorners uint8
// Name of the figure
Name [16]byte
// A two-dimensional array
Grid [2][3]int16
// A string, NULL when there is none
Label *byte
// Scale of the figure
Scale float32
// Area of the figure
Area float64
}
func (r *FooFigure) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"shape\": "...)
out = strconv.AppendUint(out, uint64(r.Shape), 10)
out = append(out, ", \"options\": "...)
out = strconv.AppendUint(out, uint64(r.Options), 10)
out = append(out, ", \"origin\": "...)
out = r.Origin.yaceJSON(out)
out = append(out, ", \"corners\": "...)
out = append(out, '[')
for i0 := range r.Corners {
if i0 > 0 {
out = append(out, ", "...)
}
out = r.Corners[i0].yaceJSON(out)
}
out = append(out, ']')
out = append(out, ", \"ncorners\": "...)
out = strconv.AppendUint(out, uint64(r.Ncorners), 10)
out = append(out, ", \"name\": "...)
out = yaceStrn(out, r.Name[:])
out = append(out, ", \"grid\": "...)
out = append(out, '[')
for i0 := range r.Grid {
if i0 > 0 {
out = append(out, ", "...)
}
out = append(out, '[')
for i1 := range r.Grid[i0] {
if i1 > 0 {
out = append(out, ", "...)
}
out = strconv.AppendInt(out, int64(r.Grid[i0][i1]), 10)
}
out = append(out, ']')
}
out = append(out, ']')
out = append(out, ", \"label\": "...)
out = yaceStr(out, unsafe.Pointer(r.Label))
out = append(out, ", \"scale\": "...)
out = yaceG(out, float64(r.Scale))
out = append(out, ", \"area\": "...)
out = yaceG(out, float64(r.Area))
return append(out, '}')
}
func (r *FooFigure) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "shape: "...)
out = strconv.AppendUint(out, uint64(r.Shape), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "options: "...)
out = strconv.AppendUint(out, uint64(r.Options), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "origin:"...)
out = append(out, '\n')
out = r.Origin.yaceYAML(out, indent+2)
out = yaceIndent(out, indent)
out = append(out, "corners: "...)
out = append(out, '[')
for i0 := range r.Corners {
if i0 > 0 {
out = append(out, ", "...)
}
out = r.Corners[i0].yaceJSON(out)
}
out = append(out, ']')
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "ncorners: "...)
out = strconv.AppendUint(out, uint64(r.Ncorners), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "name: "...)
out = yaceStrn(out, r.Name[:])
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "grid: "...)
out = append(out, '[')
for i0 := range r.Grid {
if i0 > 0 {
out = append(out, ", "...)
}
out = append(out, '[')
for i1 := range r.Grid[i0] {
if i1 > 0 {
out = append(out, ", "...)
}
out = strconv.AppendInt(out, int64(r.Grid[i0][i1]), 10)
}
out = append(out, ']')
}
out = append(out, ']')
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "label: "...)
out = yaceStr(out, unsafe.Pointer(r.Label))
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "scale: "...)
out = yaceG(out, float64(r.Scale))
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "area: "...)
out = yaceG(out, float64(r.Area))
out = append(out, '\n')
return out
}
// Fpr prints r, or null when nil, to w, as foo_figure_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooFigure) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_figure: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_figure:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooFigure) String() string {
return string(r.yaceYAML([]byte("foo_figure:\n"), 2))
}
// A 32-bit value, read as signed, as unsigned, or as the 'x' of a point
//
// A union, its members read and written through the method of
// each, as Go has no unions.
type FooValue struct {
_ [0]uint32
bytes [8]byte
}
// I is the member 'i': Signed
func (u *FooValue) I() *int32 {
return (*int32)(unsafe.Pointer(&u.bytes))
}
// U is the member 'u': Unsigned
func (u *FooValue) U() *uint32 {
return (*uint32)(unsafe.Pointer(&u.bytes))
}
// Point is the member 'point': A point, its 'x' sharing the bits of 'i'
func (u *FooValue) Point() *FooPoint {
return (*FooPoint)(unsafe.Pointer(&u.bytes))
}
func (r *FooValue) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"i\": "...)
out = strconv.AppendInt(out, int64((*r.I())), 10)
out = append(out, ", \"u\": "...)
out = strconv.AppendUint(out, uint64((*r.U())), 10)
out = append(out, ", \"point\": "...)
out = (*r.Point()).yaceJSON(out)
return append(out, '}')
}
func (r *FooValue) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "i: "...)
out = strconv.AppendInt(out, int64((*r.I())), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "u: "...)
out = strconv.AppendUint(out, uint64((*r.U())), 10)
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "point:"...)
out = append(out, '\n')
out = (*r.Point()).yaceYAML(out, indent+2)
return out
}
// Fpr prints r, or null when nil, to w, as foo_value_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooValue) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_value: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_value:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooValue) String() string {
return string(r.yaceYAML([]byte("foo_value:\n"), 2))
}
// A record laid out without padding, as a wire format is: no field after the first is aligned
//
// Packed, which Go cannot declare, as it aligns every field:
// each field is read and written by a copy, through its methods.
// The garbage collector does not see a pointer set in a field,
// so what it points to must be kept alive by other means.
type FooWire struct {
_ [0]uint8
bytes [17]byte
}
// Kind is the field 'kind': One of enum foo_shape
func (r FooWire) Kind() uint8 {
return yaceGet[uint8](r.bytes[0:])
}
// SetKind sets the field 'kind'
func (r *FooWire) SetKind(value uint8) {
yaceSet(r.bytes[0:], value)
}
// Length is the field 'length': At offset 1
func (r FooWire) Length() uint32 {
return yaceGet[uint32](r.bytes[1:])
}
// SetLength sets the field 'length'
func (r *FooWire) SetLength(value uint32) {
yaceSet(r.bytes[1:], value)
}
// At is the field 'at': A point, at offset 5
func (r FooWire) At() FooPoint {
return yaceGet[FooPoint](r.bytes[5:])
}
// SetAt sets the field 'at'
func (r *FooWire) SetAt(value FooPoint) {
yaceSet(r.bytes[5:], value)
}
// Pair is the field 'pair': An array, at offset 13
func (r FooWire) Pair() [2]uint16 {
return yaceGet[[2]uint16](r.bytes[13:])
}
// SetPair sets the field 'pair'
func (r *FooWire) SetPair(value [2]uint16) {
yaceSet(r.bytes[13:], value)
}
func (r *FooWire) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"kind\": "...)
{
v := r.Kind()
out = strconv.AppendUint(out, uint64(v), 10)
}
out = append(out, ", \"length\": "...)
{
v := r.Length()
out = strconv.AppendUint(out, uint64(v), 10)
}
out = append(out, ", \"at\": "...)
{
v := r.At()
out = v.yaceJSON(out)
}
out = append(out, ", \"pair\": "...)
{
v := r.Pair()
out = append(out, '[')
for i0 := range v {
if i0 > 0 {
out = append(out, ", "...)
}
out = strconv.AppendUint(out, uint64(v[i0]), 10)
}
out = append(out, ']')
}
return append(out, '}')
}
func (r *FooWire) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "kind: "...)
{
v := r.Kind()
out = strconv.AppendUint(out, uint64(v), 10)
}
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "length: "...)
{
v := r.Length()
out = strconv.AppendUint(out, uint64(v), 10)
}
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "at:"...)
out = append(out, '\n')
{
v := r.At()
out = v.yaceYAML(out, indent+2)
}
out = yaceIndent(out, indent)
out = append(out, "pair: "...)
{
v := r.Pair()
out = append(out, '[')
for i0 := range v {
if i0 > 0 {
out = append(out, ", "...)
}
out = strconv.AppendUint(out, uint64(v[i0]), 10)
}
out = append(out, ']')
}
out = append(out, '\n')
return out
}
// Fpr prints r, or null when nil, to w, as foo_wire_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooWire) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_wire: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_wire:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooWire) String() string {
return string(r.yaceYAML([]byte("foo_wire:\n"), 2))
}
// The status of a handle, its code a field of bits
type FooStatus struct {
// Status code, see FOO_STATUS_CODE_*
Code uint16
// Points the handle holds at most
Max uint16
}
func (r *FooStatus) yaceJSON(out []byte) []byte {
out = append(out, '{')
out = append(out, "\"code\": "...)
out = append(out, "{\"val\": "...)
out = strconv.AppendUint(out, uint64(r.Code), 10)
out = append(out, ", \"pending\": "...)
out = strconv.AppendUint(out, uint64(r.Code)&0x1>>0, 10)
out = append(out, ", \"points\": "...)
out = strconv.AppendUint(out, uint64(r.Code)&0xff0>>4, 10)
out = append(out, ", \"full\": "...)
out = strconv.AppendUint(out, uint64(r.Code)&0x8000>>15, 10)
out = append(out, '}')
out = append(out, ", \"max\": "...)
out = strconv.AppendUint(out, uint64(r.Max), 10)
return append(out, '}')
}
func (r *FooStatus) yaceYAML(out []byte, indent int) []byte {
out = yaceIndent(out, indent)
out = append(out, "code: "...)
out = append(out, "{val: 0x"...)
out = strconv.AppendUint(out, uint64(r.Code), 16)
out = append(out, ", pending: 0x"...)
out = strconv.AppendUint(out, uint64(r.Code)&0x1>>0, 16)
out = append(out, ", points: 0x"...)
out = strconv.AppendUint(out, uint64(r.Code)&0xff0>>4, 16)
out = append(out, ", full: 0x"...)
out = strconv.AppendUint(out, uint64(r.Code)&0x8000>>15, 16)
out = append(out, '}')
out = append(out, '\n')
out = yaceIndent(out, indent)
out = append(out, "max: "...)
out = strconv.AppendUint(out, uint64(r.Max), 10)
out = append(out, '\n')
return out
}
// Fpr prints r, or null when nil, to w, as foo_status_fpr() does:
// as YAML, or as JSON on one line, by flags, one of FOO_PR_*
func (r *FooStatus) Fpr(w io.Writer, flags int) error {
var out []byte
switch {
case flags&FOO_PR_JSON != 0 && r == nil:
out = append(out, "null\n"...)
case flags&FOO_PR_JSON != 0:
out = append(r.yaceJSON(out), '\n')
case r == nil:
out = append(out, "foo_status: ~\n"...)
default:
out = r.yaceYAML(append(out, "foo_status:\n"...), 2)
}
_, err := w.Write(out)
return err
}
// String is the YAML of r, as Fpr prints it
func (r FooStatus) String() string {
return string(r.yaceYAML([]byte("foo_status:\n"), 2))
}
// A count is submitted and not yet completed; bit 0 of 'code'
func (r *FooStatus) CodePending() uint16 {
return (r.Code & 0x1) >> 0
}
// SetCodePending sets the part of 'code' that CodePending reads;
// it panics on a value that does not fit the part's 1 bit.
func (r *FooStatus) SetCodePending(value uint16) {
if value > 0x1 {
panic("FooStatus.SetCodePending: " + strconv.FormatUint(uint64(value), 10) + " does not fit")
}
r.Code = r.Code&^0x1 | value<<0
}
// Points held; bits 11:4 of 'code'
func (r *FooStatus) CodePoints() uint16 {
return (r.Code & 0xff0) >> 4
}
// SetCodePoints sets the part of 'code' that CodePoints reads;
// it panics on a value that does not fit the part's 8 bits.
func (r *FooStatus) SetCodePoints(value uint16) {
if value > 0xff {
panic("FooStatus.SetCodePoints: " + strconv.FormatUint(uint64(value), 10) + " does not fit")
}
r.Code = r.Code&^0xff0 | value<<4
}
// The handle holds FOO_POINTS_MAX points; bit 15 of 'code'
func (r *FooStatus) CodeFull() uint16 {
return (r.Code & 0x8000) >> 15
}
// SetCodeFull sets the part of 'code' that CodeFull reads;
// it panics on a value that does not fit the part's 1 bit.
func (r *FooStatus) SetCodeFull(value uint16) {
if value > 0x1 {
panic("FooStatus.SetCodeFull: " + strconv.FormatUint(uint64(value), 10) + " does not fit")
}
r.Code = r.Code&^0x8000 | value<<15
}
// Called back with each point visited
//
// Parameters:
//
// - arg: The argument given along with the callback
// - point: The point visited
//
// Returns 0 to go on, anything else to stop.
type FooVisitCb unsafe.Pointer
// Called back when a count submitted completes
//
// Parameters:
//
// - arg: The argument given along with the callback
// - count: The number of points when it completed
type FooDoneCb unsafe.Pointer
// Called back with each point added to a handle watched
//
// Parameters:
//
// - arg: The argument given along with the callback
// - point: The point added
type FooAddedCb unsafe.Pointer
// The version of the library
//
// Returns The version, as "MAJOR.MINOR.PATCH".
//
// Foo_version calls foo_version.
func Foo_version() *byte {
return (*byte)(unsafe.Pointer(C.foo_version()))
}
// Open a handle holding no points
//
// Parameters:
//
// - name: Name of the handle, copied
// - handle: Set to the handle opened
//
// Returns 0 on success, -EINVAL when 'name' or 'handle' is NULL, -ENOMEM when memory ran out.
//
// Foo_open calls foo_open.
func Foo_open(name *byte, handle **FooHandle) int32 {
return int32(C.foo_open((*C.char)(unsafe.Pointer(name)), (**C.struct_foo_handle)(unsafe.Pointer(handle))))
}
// Close a handle
//
// Parameters:
//
// - handle: The handle to close, NULL is ignored
//
// Foo_close calls foo_close.
func Foo_close(handle *FooHandle) {
C.foo_close((*C.struct_foo_handle)(unsafe.Pointer(handle)))
}
// The name the handle was opened with
//
// Parameters:
//
// - handle: The handle
//
// Returns The name, owned by the handle.
//
// Foo_name calls foo_name.
func Foo_name(handle *FooHandle) *byte {
return (*byte)(unsafe.Pointer(C.foo_name((*C.struct_foo_handle)(unsafe.Pointer(handle)))))
}
// Add a point to the handle
//
// Parameters:
//
// - handle: The handle
// - point: The point to add, copied
//
// Returns 0 on success, -ENOSPC when the handle holds FOO_POINTS_MAX points.
//
// Foo_point_add calls foo_point_add.
func Foo_point_add(handle *FooHandle, point *FooPoint) int32 {
return int32(C.foo_point_add((*C.struct_foo_handle)(unsafe.Pointer(handle)), (*C.struct_foo_point)(unsafe.Pointer(point))))
}
// Add points to the handle, as many as it has room for
//
// Parameters:
//
// - handle: The handle
// - points: The points to add, copied
// - npoints: The number of points
//
// Returns The number of points added, -ENOSPC when there was room for none.
//
// Foo_point_add_many calls foo_point_add_many.
func Foo_point_add_many(handle *FooHandle, points *FooPoint, npoints uintptr) int {
return int(C.foo_point_add_many((*C.struct_foo_handle)(unsafe.Pointer(handle)), (*C.struct_foo_point)(unsafe.Pointer(points)), C.size_t(npoints)))
}
// The number of points held
//
// Parameters:
//
// - handle: The handle
//
// Returns The number of points.
//
// Foo_point_count calls foo_point_count.
func Foo_point_count(handle *FooHandle) uintptr {
return uintptr(C.foo_point_count((*C.struct_foo_handle)(unsafe.Pointer(handle))))
}
// A point held by the handle
//
// Parameters:
//
// - handle: The handle
// - idx: Index of the point
//
// Returns The point, NULL when 'idx' is past the last one.
//
// Foo_point_get calls foo_point_get.
func Foo_point_get(handle *FooHandle, idx uintptr) *FooPoint {
return (*FooPoint)(unsafe.Pointer(C.foo_point_get((*C.struct_foo_handle)(unsafe.Pointer(handle)), C.size_t(idx))))
}
// Copy the points held, as many as fit
//
// Parameters:
//
// - handle: The handle
// - points: Where to copy the points to
// - npoints: The number of points that fit
//
// Returns The number of points copied.
//
// Foo_point_copy calls foo_point_copy.
func Foo_point_copy(handle *FooHandle, points *FooPoint, npoints uintptr) int {
return int(C.foo_point_copy((*C.struct_foo_handle)(unsafe.Pointer(handle)), (*C.struct_foo_point)(unsafe.Pointer(points)), C.size_t(npoints)))
}
// Watch the points added to the handle, from now until it is closed
//
// Parameters:
//
// - handle: The handle
// - added: Called with each point added, until the handle is closed
// - arg: Given to 'added'
//
// Returns 0 on success, -EBUSY when the handle is watched already.
//
// Foo_point_watch calls foo_point_watch.
func Foo_point_watch(handle *FooHandle, added FooAddedCb, arg unsafe.Pointer) int32 {
return int32(C.foo_point_watch((*C.struct_foo_handle)(unsafe.Pointer(handle)), (C.foo_added_cb)(unsafe.Pointer(added)), arg))
}
// Visit the points in the order they were added
//
// Parameters:
//
// - handle: The handle
// - visit: Called for each point, until it returns non-zero
// - arg: Given to 'visit'
//
// Returns The number of points visited, -EINVAL when 'visit' is NULL.
//
// Foo_point_visit calls foo_point_visit.
func Foo_point_visit(handle *FooHandle, visit FooVisitCb, arg unsafe.Pointer) int {
return int(C.foo_point_visit((*C.struct_foo_handle)(unsafe.Pointer(handle)), (C.foo_visit_cb)(unsafe.Pointer(visit)), arg))
}
// Visit the points with a visitor; as foo_point_visit()
//
// Parameters:
//
// - handle: The handle
// - visitor: The callback and its argument
//
// Returns The number of points visited, -EINVAL when the callback is NULL.
//
// Foo_point_visit_with calls foo_point_visit_with.
func Foo_point_visit_with(handle *FooHandle, visitor *FooVisitor) int {
return int(C.foo_point_visit_with((*C.struct_foo_handle)(unsafe.Pointer(handle)), (*C.struct_foo_visitor)(unsafe.Pointer(visitor))))
}
// Submit a count of the points, completed by foo_count_complete()
//
// Parameters:
//
// - handle: The handle
// - done: Called once, by foo_count_complete(), with the number of points
// - arg: Given to 'done'
//
// Returns 0, -EBUSY when a count is submitted and not yet completed.
//
// Foo_count_submit calls foo_count_submit.
func Foo_count_submit(handle *FooHandle, done FooDoneCb, arg unsafe.Pointer) int32 {
return int32(C.foo_count_submit((*C.struct_foo_handle)(unsafe.Pointer(handle)), (C.foo_done_cb)(unsafe.Pointer(done)), arg))
}
// Complete the count submitted, if any, calling its callback
//
// Parameters:
//
// - handle: The handle
//
// Returns The number of counts completed, 0 or 1.
//
// Foo_count_complete calls foo_count_complete.
func Foo_count_complete(handle *FooHandle) uintptr {
return uintptr(C.foo_count_complete((*C.struct_foo_handle)(unsafe.Pointer(handle))))
}
// The status of the handle
//
// Parameters:
//
// - handle: The handle
// - status: The status to fill in
//
// Foo_status_get calls foo_status_get.
func Foo_status_get(handle *FooHandle, status *FooStatus) {
C.foo_status_get((*C.struct_foo_handle)(unsafe.Pointer(handle)), (*C.struct_foo_status)(unsafe.Pointer(status)))
}
// Fill in a value of every kind of scalar, the limits of the fixed-width ones
//
// Parameters:
//
// - scalars: The values to fill in
//
// Foo_scalars_fill calls foo_scalars_fill.
func Foo_scalars_fill(scalars *FooScalars) {
C.foo_scalars_fill((*C.struct_foo_scalars)(unsafe.Pointer(scalars)))
}
// Fill in a figure of the given shape
//
// Parameters:
//
// - figure: The figure to fill in
// - shape: One of enum foo_shape
//
// Returns 0 on success, -EINVAL when 'shape' is none of enum foo_shape.
//
// Foo_figure_fill calls foo_figure_fill.
func Foo_figure_fill(figure *FooFigure, shape uint32) int32 {
return int32(C.foo_figure_fill((*C.struct_foo_figure)(unsafe.Pointer(figure)), C.uint32_t(shape)))
}
// Set a value, clearing the bits it does not use
//
// Parameters:
//
// - value: The value to set
// - i: What to set it to
//
// Foo_value_set calls foo_value_set.
func Foo_value_set(value *FooValue, i int32) {
C.foo_value_set((*C.union_foo_value)(unsafe.Pointer(value)), C.int32_t(i))
}
// Fill in a packed record
//
// Parameters:
//
// - wire: The record to fill in
//
// Foo_wire_fill calls foo_wire_fill.
func Foo_wire_fill(wire *FooWire) {
C.foo_wire_fill((*C.struct_foo_wire)(unsafe.Pointer(wire)))
}
// yaceErrno is the error of the negative errno a C function returned
func yaceErrno(function string, ret int64) error {
return fmt.Errorf("%s: %w", function, syscall.Errno(-ret))
}
// yaceClosure is a Go function given to C, and whether C calls it once
type yaceClosure struct {
fn any
once bool
}
// yaceKeep is C memory holding a handle of fn, as C may not hold a Go pointer,
// for C to give to the trampoline of the callback
func yaceKeep(fn any, once bool) unsafe.Pointer {
ctx := C.malloc(C.size_t(unsafe.Sizeof(C.uintptr_t(0))))
*(*C.uintptr_t)(ctx) = C.uintptr_t(cgo.NewHandle(yaceClosure{fn, once}))
return ctx
}
// yaceRelease releases what yaceKeep made; nil is none
func yaceRelease(ctx unsafe.Pointer) {
if ctx != nil {
cgo.Handle(*(*C.uintptr_t)(ctx)).Delete()
C.free(ctx)
}
}
// yaceCalled is the function of ctx, released when it is called once
func yaceCalled(ctx unsafe.Pointer) any {
closure := cgo.Handle(*(*C.uintptr_t)(ctx)).Value().(yaceClosure)
if closure.once {
yaceRelease(ctx)
}
return closure.fn
}
// FooAddedCbFunc is a function given as a FooAddedCb, without its context
type FooAddedCbFunc func(point *FooPoint)
// FooVisitCbFunc is a function given as a FooVisitCb, without its context
type FooVisitCbFunc func(point *FooPoint) int32
// FooDoneCbFunc is a function given as a FooDoneCb, without its context
type FooDoneCbFunc func(count uintptr)
// A collection of points, opened with foo_open() and closed with foo_close()
//
// Handle owns a *FooHandle, released by Close, which calls foo_close.
type Handle struct {
ptr *FooHandle
keep []unsafe.Pointer
}
// Ptr is the raw pointer, still owned by the Handle
func (h *Handle) Ptr() *FooHandle {
return h.ptr
}
// Open a handle holding no points
//
// Parameters:
//
// - name: Name of the handle, copied
//
// Errors: foo_open() returns: 0 on success, -EINVAL when 'name' or 'handle' is NULL, -ENOMEM when memory ran out.
//
// Open calls foo_open.
func Open(name string) (*Handle, error) {
name_c := C.CString(name)
defer C.free(unsafe.Pointer(name_c))
var handle_out *FooHandle
ret := C.foo_open(name_c, (**C.struct_foo_handle)(unsafe.Pointer(&handle_out)))
if ret < 0 {
return nil, yaceErrno("foo_open", int64(ret))
}
if handle_out == nil {
return nil, errors.New("foo_open() gave no handle")
}
handle_made := &Handle{ptr: handle_out}
return handle_made, nil
}
// The name the handle was opened with
//
// Returns The name, owned by the handle.
//
// Name calls foo_name.
func (h *Handle) Name() string {
ret := C.foo_name((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)))
return C.GoString(ret)
}
// Add a point to the handle
//
// Parameters:
//
// - point: The point to add, copied
//
// Errors: foo_point_add() returns: 0 on success, -ENOSPC when the handle holds FOO_POINTS_MAX points.
//
// PointAdd calls foo_point_add.
func (h *Handle) PointAdd(point *FooPoint) error {
ret := C.foo_point_add((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), (*C.struct_foo_point)(unsafe.Pointer(point)))
if ret < 0 {
return yaceErrno("foo_point_add", int64(ret))
}
return nil
}
// Add points to the handle, as many as it has room for
//
// Parameters:
//
// - points: The points to add, copied
//
// Errors: foo_point_add_many() returns: The number of points added, -ENOSPC when there was room for none.
//
// PointAddMany calls foo_point_add_many.
func (h *Handle) PointAddMany(points []FooPoint) (int, error) {
ret := C.foo_point_add_many((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), (*C.struct_foo_point)(unsafe.Pointer(unsafe.SliceData(points))), C.size_t(len(points)))
if ret < 0 {
return 0, yaceErrno("foo_point_add_many", int64(ret))
}
return int(ret), nil
}
// The number of points held
//
// Returns The number of points.
//
// PointCount calls foo_point_count.
func (h *Handle) PointCount() uintptr {
ret := C.foo_point_count((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)))
return uintptr(ret)
}
// A point held by the handle
//
// Parameters:
//
// - idx: Index of the point
//
// Returns The point, NULL when 'idx' is past the last one.
//
// PointGet calls foo_point_get.
func (h *Handle) PointGet(idx uintptr) (FooPoint, bool) {
ret := C.foo_point_get((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), C.size_t(idx))
var ret_val FooPoint
if ret != nil {
ret_val = *(*FooPoint)(unsafe.Pointer(ret))
}
return ret_val, ret != nil
}
// Copy the points held, as many as fit
//
// Parameters:
//
// - npoints: The number of points that fit
//
// Errors: foo_point_copy() returns: The number of points copied.
//
// PointCopy calls foo_point_copy.
func (h *Handle) PointCopy(points []FooPoint) ([]FooPoint, error) {
ret := C.foo_point_copy((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), (*C.struct_foo_point)(unsafe.Pointer(unsafe.SliceData(points))), C.size_t(len(points)))
if ret < 0 {
return nil, yaceErrno("foo_point_copy", int64(ret))
}
return points[:ret], nil
}
// Watch the points added to the handle, from now until it is closed
//
// Parameters:
//
// - added: Called with each point added, until the handle is closed
//
// Errors: foo_point_watch() returns: 0 on success, -EBUSY when the handle is watched already.
//
// PointWatch calls foo_point_watch.
//
// C keeps 'added' until the handle is destroyed.
func (h *Handle) PointWatch(added FooAddedCbFunc) error {
added_ctx := yaceKeep(added, false)
ret := C.foo_point_watch((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), C.foo_added_cb(C.yace_foo_added_cb), added_ctx)
if ret < 0 {
yaceRelease(added_ctx)
return yaceErrno("foo_point_watch", int64(ret))
}
h.keep = append(h.keep, added_ctx)
return nil
}
// Visit the points in the order they were added
//
// Parameters:
//
// - visit: Called for each point, until it returns non-zero
//
// Errors: foo_point_visit() returns: The number of points visited, -EINVAL when 'visit' is NULL.
//
// PointVisit calls foo_point_visit.
func (h *Handle) PointVisit(visit FooVisitCbFunc) (int, error) {
visit_ctx := yaceKeep(visit, false)
defer yaceRelease(visit_ctx)
ret := C.foo_point_visit((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), C.foo_visit_cb(C.yace_foo_visit_cb), visit_ctx)
if ret < 0 {
return 0, yaceErrno("foo_point_visit", int64(ret))
}
return int(ret), nil
}
// Visit the points with a visitor; as foo_point_visit()
//
// Parameters:
//
// - visitor: The callback and its argument
//
// Errors: foo_point_visit_with() returns: The number of points visited, -EINVAL when the callback is NULL.
//
// PointVisitWith calls foo_point_visit_with.
func (h *Handle) PointVisitWith(visitor *FooVisitor) (int, error) {
ret := C.foo_point_visit_with((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), (*C.struct_foo_visitor)(unsafe.Pointer(visitor)))
if ret < 0 {
return 0, yaceErrno("foo_point_visit_with", int64(ret))
}
return int(ret), nil
}
// Submit a count of the points, completed by foo_count_complete()
//
// Parameters:
//
// - done: Called once, by foo_count_complete(), with the number of points
//
// Errors: foo_count_submit() returns: 0, -EBUSY when a count is submitted and not yet completed.
//
// CountSubmit calls foo_count_submit.
//
// C keeps 'done' until it has been called, once.
func (h *Handle) CountSubmit(done FooDoneCbFunc) error {
done_ctx := yaceKeep(done, true)
ret := C.foo_count_submit((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), C.foo_done_cb(C.yace_foo_done_cb), done_ctx)
if ret < 0 {
yaceRelease(done_ctx)
return yaceErrno("foo_count_submit", int64(ret))
}
return nil
}
// Complete the count submitted, if any, calling its callback
//
// Returns The number of counts completed, 0 or 1.
//
// CountComplete calls foo_count_complete.
func (h *Handle) CountComplete() uintptr {
ret := C.foo_count_complete((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)))
return uintptr(ret)
}
// The status of the handle
//
// StatusGet calls foo_status_get.
func (h *Handle) StatusGet() FooStatus {
var status_out FooStatus
C.foo_status_get((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)), (*C.struct_foo_status)(unsafe.Pointer(&status_out)))
return status_out
}
// Close a handle
//
// Close calls foo_close.
func (h *Handle) Close() {
C.foo_close((*C.struct_foo_handle)(unsafe.Pointer(h.ptr)))
for _, ctx := range h.keep {
yaceRelease(ctx)
}
h.keep = nil
h.ptr = nil
}
// The version of the library
//
// Returns The version, as "MAJOR.MINOR.PATCH".
//
// Version calls foo_version.
func Version() string {
ret := C.foo_version()
return C.GoString(ret)
}
// Fill in a value of every kind of scalar, the limits of the fixed-width ones
//
// ScalarsFill calls foo_scalars_fill.
func ScalarsFill() FooScalars {
var scalars_out FooScalars
C.foo_scalars_fill((*C.struct_foo_scalars)(unsafe.Pointer(&scalars_out)))
return scalars_out
}
// Fill in a figure of the given shape
//
// Parameters:
//
// - shape: One of enum foo_shape
//
// Errors: foo_figure_fill() returns: 0 on success, -EINVAL when 'shape' is none of enum foo_shape.
//
// FigureFill calls foo_figure_fill.
func FigureFill(shape uint32) (FooFigure, error) {
var figure_out FooFigure
ret := C.foo_figure_fill((*C.struct_foo_figure)(unsafe.Pointer(&figure_out)), C.uint32_t(shape))
if ret < 0 {
return FooFigure{}, yaceErrno("foo_figure_fill", int64(ret))
}
return figure_out, nil
}
// Set a value, clearing the bits it does not use
//
// Parameters:
//
// - i: What to set it to
//
// ValueSet calls foo_value_set.
func ValueSet(i int32) FooValue {
var value_out FooValue
C.foo_value_set((*C.union_foo_value)(unsafe.Pointer(&value_out)), C.int32_t(i))
return value_out
}
// Fill in a packed record
//
// WireFill calls foo_wire_fill.
func WireFill() FooWire {
var wire_out FooWire
C.foo_wire_fill((*C.struct_foo_wire)(unsafe.Pointer(&wire_out)))
return wire_out
}
//export yace_go_foo_added_cb
func yace_go_foo_added_cb(ctx unsafe.Pointer, a1 unsafe.Pointer) {
yaceCalled(ctx).(FooAddedCbFunc)((*FooPoint)(a1))
}
//export yace_go_foo_visit_cb
func yace_go_foo_visit_cb(ctx unsafe.Pointer, a1 unsafe.Pointer) C.int {
return C.int(yaceCalled(ctx).(FooVisitCbFunc)((*FooPoint)(a1)))
}
//export yace_go_foo_done_cb
func yace_go_foo_done_cb(ctx unsafe.Pointer, a1 C.size_t) {
yaceCalled(ctx).(FooDoneCbFunc)(uintptr(a1))
}
Implementation¶
The Go target: a cgo package binding the API, in two layers, the raw one declaring the C API as C has it and the idiomatic one over it, with every struct and union printing itself as the C API’s pretty-printers print it, and a check of what it generated
Emits, into <output>/go, the module of the package:
go.mod, the module, named as the prefix<prefix>.go, the bindings<prefix>_link.go, linking the library, unless built with the tag<prefix>_no_link<prefix>_no_link.c, what is linked with that tag in place of the library<prefix>_callbacks.c, the C side of the closures given as callbackslib<prefix>.h, the C API, as the C target emits it, which the package includescheck/main.go, the check program
The module needs Go 1.22 and a C compiler, as cgo does.
- class yace.targets.go.target.Go(output: Path, include: List[Path] | None = None, options: Dict[str, str] | None = None)¶
- yace.targets.go.target.imports(lines: List[str]) List[str]¶
The packages ‘lines’ of Go use, other than in comments and strings
Go code for the IR: names, the Go type of each IR type and the type cgo gives
it, the conversions between the two, and the methods of the records. The raw
layer declares the records as Go structs of the C layout, with exported fields,
as cgo’s own types are of no use outside the package; a union is its bytes,
read and written through a method per member. Pointers are Go pointers, which
may point to C memory; void * and function pointers are unsafe.Pointer.
- class yace.targets.go.ggen.Namer(model: Model)¶
The Go names of the package: of the types, CamelCase of the C name, or the C name itself, exported, where two would get the same one; of the constants and raw functions, the C name exported. Each is other than those named before it, by a trailing ‘_’.
- by_value(typ) bool¶
Whether Go can hold a ‘typ’ by value: not one it only knows the name of, such as a va_list, declared outside the headers
- ctype(typ, param: bool = False) str¶
The type cgo gives ‘typ’
- from_c(typ, expr: str) str¶
‘expr’, as cgo gives a ‘typ’, as its Go type; a record, addressable
- gotype(typ, param: bool = False) str¶
The Go type of ‘typ’; a parameter’s arrays are pointers, as in C
- is_opaque(typ) bool¶
Whether ‘typ’ is one Go knows nothing of but its name
- kind(typ) str¶
How a value of ‘typ’ crosses to C: as a ‘scalar’, a ‘pointer’, a ‘record’ by value, or ‘none’, void
- to_c(typ, expr: str, param: bool = True) str¶
‘expr’, of the Go type of ‘typ’, as cgo takes it
- type_name(typ) str¶
The name of the record, enum or typedef ‘typ’ names
- class yace.targets.go.ggen.Printer(namer: Namer, records: Records)¶
The Go statements appending to the []byte ‘out’ a value of a type, as the pretty-printers of the C API print it
- bound(record, field, lines: List[str]) List[str]¶
‘lines’, in a block binding the local ‘v’ to a copy of ‘field’ of a packed record, if they use it, for them to take its address
- named(record) list¶
The fields printed: those with a name, not padding bit-fields
- parts(field, expr: str, base: int, quote: str) List[str]¶
The value of a field of bits and of each of its parts, as a mapping on one line, with the keys quoted by ‘quote’, the values in ‘base’
- place(record, field) str¶
The expression of ‘field’ of the record ‘r’; of a packed record, the local ‘v’, see bound()
- printable(typ)¶
The record ‘typ’ is, if it is one with printers
- class yace.targets.go.ggen.Records(namer: Namer, complete: List)¶
The Go declarations of the records, and their methods: the members of a union, the printers and the parts of the fields of bits
- accessors(record, name: str) List[str]¶
The methods reading and writing the parts of the fields of bits of ‘record’; a value that does not fit its part panics. Of a packed record, a getter has a value receiver, as those of its fields do
- bytes(record) List[str]¶
The fields of a record kept as its bytes, aligned as the record
- field_names(record) Dict[str, str]¶
The Go names of the fields of a struct, or of the methods of the members of a union, by C name
- is_bytes(record) bool¶
Whether ‘record’ is declared as its bytes: a blob, or packed, as Go aligns every field
- is_flexible(record, field) bool¶
Whether ‘field’ is a flexible array, which Go cannot declare: a zero-sized last field would pad the struct
- members(record, name: str) List[str]¶
The method of each member of a union, the member in its bytes
- method_names(record) Dict[str, str]¶
The names of the methods of ‘record’, other than its fields’
- packed_fields(record, name: str) List[str]¶
The methods reading and writing each field of a packed record, in its bytes at its offset, which may not be aligned for it; a getter has a value receiver, so that it reads what another getter returns
- printers(record, name: str, prefix: str) List[str]¶
Fpr() and String(), printing what the C API’s pretty-printers print, without calling them
- class yace.targets.go.ggen.Registry(taken=())¶
Names, each other than those before it, by a trailing ‘_’
- yace.targets.go.ggen.align(rows: List[Tuple[List[str], List[str]]], indent: str = '\t') List[str]¶
The lines of ‘rows’, each its comment lines and its cells, with the cells padded as gofmt pads them: across the rows that follow each other with no comment line between them
- yace.targets.go.ggen.doc_lines(doc, errors: str = '') List[str]¶
The lines of a doc comment, unindented, which Go would read as code, and a paragraph of one line ending in a full stop, which Go would read as a heading otherwise; ‘errors’ says when it returns an error
- yace.targets.go.ggen.export(name: str) str¶
‘name’, exported, as Go exports what begins with an upper-case letter
- yace.targets.go.ggen.go_quote(text: str) str¶
‘text’ as a Go string literal
- yace.targets.go.ggen.ident(name: str) str¶
‘name’, usable as a local Go identifier
The raw layer of the Go package: the constants, enums, types and functions of the C API, by their C names, exported. A function is a Go function calling it through cgo, converting what it is given; one cgo cannot call, such as a variadic one, is not bound, which its place in the package says.
- class yace.targets.go.raw.Raw(model: Model, namer: Namer, records: Records)¶
The raw layer, and the names it declares, before any other
- render() List[str]¶
The raw layer, after the declarations of the package’s own
- reserved() set¶
What a parameter must not be named: what a body may use
- unbindable(function) str | None¶
Why cgo cannot call ‘function’, if it cannot
- unsized_pointee(typ) bool¶
Whether ‘typ’ holds a pointer to an array of no length, ‘int (*)[]’
- yace.targets.go.raw.doc(lines: List[str], *more: str) List[str]¶
A doc comment of ‘lines’, then of ‘more’, a paragraph of its own
- yace.targets.go.raw.param_names(names, reserved) List[str]¶
The Go names of parameters, by their C names, none of them ‘reserved’ nor shared; the unnamed and ‘_’ are ‘arg<n>’
The idiomatic Go layer of the package, over the C functions: handles as
structs with their methods, errors as the last of the values returned, a
syscall.Errno, what is written through [out] pointers returned, slices
for arrays, a caller’s slice for those written, strings for const char *,
nil where NULL is allowed, and Go functions for callbacks. See
yace.targets.idiom for what is derived from where. Names are
CamelCase, exported, without the prefix.
A closure given to C is kept in a runtime/cgo.Handle, held in C memory, as
cgo forbids C to keep a Go pointer: its value is what the C trampoline of the
callback gives back to the Go function it exports. It is released as the
callback’s @lifetime says: when the call returns, once it has been called,
or when the handle is destroyed.