Files
five/hbrt/pcserial.go
Charles KWON OhJun 59568f3301 Five v0.9 — Harbour + Go fusion language
- Compiler: PP → Lexer → Parser → Analyzer → Gengo pipeline
- Parser: 232/236 (98%) Harbour compatibility, registry-based dispatch
- RTL: 351 Harbour-compatible functions
- RDD: DBF/NTX/CDX engines with Rushmore bitmap optimization
- Go Interop: IMPORT + pkg.Func() + obj:Method() with FastPath (15M calls/sec)
- HB_FUNC API: Full Harbour C API compatible Go bridge
- Concurrency: SPAWN/LAUNCH/GOROUTINE, <-, WATCH, PARALLEL FOR, ASYNC/AWAIT
- Extensions: Multi-return, DEFER, Slice, f-string, Nil-safe ?:, CONST
- Macro Compiler: Runtime AST parsing and evaluation
- Debugger: TUI debugger with source display, breakpoints, stepping
- FRB: Native + Pcode dual mode runtime binary
- Tests: 13 packages ALL PASS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:41:50 +09:00

119 lines
2.6 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// Pcode serialization/deserialization for FRB files.
package hbrt
import (
"encoding/binary"
"fmt"
)
// SerializePcodeModule writes a PcodeModule to bytes.
// Format:
// uint16 funcCount
// for each func:
// uint16 nameLen + name
// uint16 params
// uint16 locals
// uint32 codeLen + code
func SerializePcodeModule(mod *PcodeModule) []byte {
var buf []byte
// Function count
var tmp [2]byte
binary.LittleEndian.PutUint16(tmp[:], uint16(len(mod.Funcs)))
buf = append(buf, tmp[:]...)
for name, fn := range mod.Funcs {
// Name
binary.LittleEndian.PutUint16(tmp[:], uint16(len(name)))
buf = append(buf, tmp[:]...)
buf = append(buf, []byte(name)...)
// Params + Locals
binary.LittleEndian.PutUint16(tmp[:], uint16(fn.Params))
buf = append(buf, tmp[:]...)
binary.LittleEndian.PutUint16(tmp[:], uint16(fn.Locals))
buf = append(buf, tmp[:]...)
// Code
var tmp4 [4]byte
binary.LittleEndian.PutUint32(tmp4[:], uint32(len(fn.Code)))
buf = append(buf, tmp4[:]...)
buf = append(buf, fn.Code...)
}
return buf
}
// DeserializePcodeModule reads a PcodeModule from bytes.
func DeserializePcodeModule(data []byte) (*PcodeModule, error) {
if len(data) < 2 {
return nil, fmt.Errorf("pcode data too short")
}
mod := &PcodeModule{
Funcs: make(map[string]*PcodeFunc),
}
pos := 0
funcCount := int(binary.LittleEndian.Uint16(data[pos:]))
pos += 2
for i := 0; i < funcCount; i++ {
if pos+2 > len(data) {
return nil, fmt.Errorf("truncated pcode at func %d", i)
}
// Name
nameLen := int(binary.LittleEndian.Uint16(data[pos:]))
pos += 2
name := string(data[pos : pos+nameLen])
pos += nameLen
// Params + Locals
params := int(binary.LittleEndian.Uint16(data[pos:]))
pos += 2
locals := int(binary.LittleEndian.Uint16(data[pos:]))
pos += 2
// Code
codeLen := int(binary.LittleEndian.Uint32(data[pos:]))
pos += 4
code := make([]byte, codeLen)
copy(code, data[pos:pos+codeLen])
pos += codeLen
mod.Funcs[name] = &PcodeFunc{
Name: name,
Code: code,
Params: params,
Locals: locals,
}
}
return mod, nil
}
// SymDef is a helper for creating modules from pcode.
type SymDef struct {
Name string
Scope uint16
Fn func(*Thread)
}
// NewModuleFromDefs creates a Module from SymDef slice.
func NewModuleFromDefs(name string, defs []SymDef) *Module {
syms := make([]Symbol, len(defs))
for i, d := range defs {
syms[i] = Symbol{
Name: d.Name,
Scope: d.Scope,
Func: d.Fn,
}
}
return &Module{Name: name, Symbols: syms}
}