lc

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

Lc - Language Toolkit for Go

Go Reference Go Report Card

go get github.com/pt-main/lc

Lc is a production-oriented toolkit for building language runtimes, compiler-like execution pipelines, command interpreters, and bytecode-driven processors in Go.

It is intentionally straightforward to adopt, while preserving industrial runtime properties:

  • explicit execution lifecycle,
  • deterministic output assembly,
  • context-aware cancellation,
  • thread-safe core primitives,
  • clear extension contracts for parsers and command handlers.

Lc does not enforce one grammar style or one VM model.
Instead, it gives you one runtime surface with two engine backends:

  • String Engine for text-first processing.
  • Byte Engine for binary instruction execution.

Engine model

String Engine

Best for command languages, script-like syntaxes, config runtimes, and text transformation flows.

Default lifecycle:

  1. store input in scope;
  2. parse input to []ParsedNode;
  3. dispatch handlers by ParsedNode.Switch;
  4. emit output through UEP.Generator (if need).
Byte Engine

Best for opcode streams, compact protocol runtimes, and binary execution loops.

Default lifecycle:

  1. store input in scope (INPUT []byte);
  2. parse input to []ParsedBytes;
  3. decode opcode from ParsedBytes.Switch bytes using configured endianness;
  4. dispatch opcode handler;
  5. advance instruction pointer automatically or manually.

Quick start - String Engine

package main

import (
	"fmt"
	"strings"

	"github.com/pt-main/lc"
	enginepkg "github.com/pt-main/lc/engine"
	"github.com/pt-main/lc/stringParsing"
)

func main() {
	parser := &stringParsing.Parser2{}

	engine, err := lc.NewEngineBuilder(lc.StringEngineType).
		WithPipeline([]string{"main"}).
		WithStringParser(parser).
		WithDefaultEvents(true).
		Build()
	if err != nil {
		panic(err)
	}

	err = engine.NewCommandString("print", func(se *enginepkg.StringEngine, node stringParsing.ParsedNode) error {
		args, _ := node.Metadata["args"].(string)
		return se.UEP.Generator.AddString(args, "main")
	}, "append text to output")
	if err != nil {
		panic(err)
	}

	err = engine.ProcessString(strings.Join([]string{
		"print service_start",
		"print service_ready",
	}, "\n"))
	if err != nil {
		panic(err)
	}

	out, err := engine.GetUEP().Generator.GetStringRes("\n")
	if err != nil {
		panic(err)
	}
	fmt.Println(out)
}

Quick start - Byte Engine

package main

import (
	"fmt"

	"github.com/pt-main/lc"
	"github.com/pt-main/lc/byteParsing"
	enginepkg "github.com/pt-main/lc/engine"
	"github.com/pt-main/lc/tooling/bytecode"
)

func main() {
	parser := &byteParsing.Parser1{
		Config: byteParsing.Parser1Config{
			GConfig: bytecode.GenerationConfig{
				CommandBytelen:   1,
				ArgscountBytelen: 1,
				ArglenBytelen:    1,
				Endianess:        bytecode.LittleEndian,
			},
			Shifter: bytecode.Shift{},
		},
	}

	engine, err := lc.NewEngineBuilder(lc.ByteEngineType).
		WithPipeline([]string{"main"}).
		WithByteParser(parser).
		WithDefaultEvents(true).
		Build()
	if err != nil {
		panic(err)
	}

	err = engine.NewCommandByte(1, func(be *enginepkg.ByteEngine, node byteParsing.ParsedBytes) error {
		return be.UEP.Generator.AddBytes(node.Raw, "main")
	}, "mirror instruction bytes", true)
	if err != nil {
		panic(err)
	}

	code := []byte{
		0x01, 0x01, 0x03, 0x61, 0x62, 0x63, // opcode=1, args=1, argLen=3, arg="abc"
	}

	err = engine.ProcessBytes(code)
	if err != nil {
		panic(err)
	}

	out, err := engine.GetUEP().Generator.GetBytesRes()
	if err != nil {
		panic(err)
	}
	fmt.Printf("%x\n", out)
}

Industrial setup pattern

For production embedding, typical builder configuration includes:

  • explicit pipeline points (e.g. bootstrap, main, finalize);
  • shared service context;
  • structured logger instance;
  • preloaded scope values (tenant/env/runtime metadata);
  • custom events for audit/metrics/tracing.

Example:

engine, err := lc.NewEngineBuilder(lc.StringEngineType).
	WithPipeline([]string{"bootstrap", "main", "finalize"}).
	WithContext(ctx).
	WithDefaultEvents(true).
	WithLogger(logger).
	WithScope(scope).
	WithStringParser(parser).
	Build()

Built-in parser modules

stringParsing
  • Parser1:
    • regex grammar matching,
    • named capture-group metadata,
    • line continuation support,
    • bracket-balance support.
  • Parser2: compact line-oriented command args parser.
  • Lexer: ordered regexp2 tokenizer with __prev / __next node links.
byteParsing
  • Parser1: binary parser with configurable field lengths and endianness.
  • ParsedBytes model with Switch, Args, Raw, and Metadata.

Public runtime API overview

Processing
  • ProcessString(input string) error
  • ProcessStringWithCtx(input string, ctx context.Context) error
  • ProcessBytes(input []byte) error
  • ProcessBytesWithCtx(input []byte, ctx context.Context) error
Command registration
  • NewCommandString(cmdSwitch string, handler ..., doc string) error
  • NewCommandByte(opcode int, handler ..., name string, autoBytecodeIdxShift bool) error
Byte instruction pointer controls
  • AddToBytecodeIdx(n int)
  • SetBytecodeIdx(n int)
  • GetBytecodeIdx() (*int, error)

Execution semantics

  • Event handlers run in registration order.
  • Generator result follows declared pipeline order.
  • Process*WithCtx respects cancellation/deadline.
  • Default String dispatch skips unknown commands.
  • Default Byte dispatch expects valid opcode/autoshift registration for processed commands.

Reserved scope keys used by default events

String keys:

  • INPUT string
  • PARSED []ParsedNode

Byte keys:

  • INPUT []byte
  • PARSED []ParsedBytes
  • ENDIANESS int
  • BYECODE_IDX *int

Treat these names as reserved runtime contract keys.

Observability

Lc provides core mechanisms for operational visibility:

  • thread-safe core.Logger,
  • event lifecycle hooks (call start/call end),
  • centralized runtime scope for contextual metadata,
  • structured error wrapping in default event flows.

Repository structure

  • builder.go - fluent builder.
  • engine.go - universal runtime wrapper and command registration.
  • main.go - public constructors for String/Byte engines.
  • engine/ - concrete engine implementations.
  • engine/core/ - generator, events, logger, shared params.
  • events/ - default parse/call handlers.
  • stringParsing/ - text parser ecosystem.
  • byteParsing/ - byte parser ecosystem.
  • tooling/bytecode/ - byte conversion and shift helpers.

Validation

go test ./...

License

MIT - see LICENSE.

By Pt.

Documentation

Index

Constants

View Source
const (
	ByteEngineType = iota
	StringEngineType
)
View Source
const Version = "1.0.0"

Variables

This section is empty.

Functions

func NewByteEngine

func NewByteEngine(
	generator_res_type int,
	pipeline []string,
	add_default_events bool,
	parser byteParsing.ParserInterface,
	endianess int,
	colorEnable bool,
	context context.Context,
) *engine.ByteEngine

NewByteEngine creates a byte-oriented engine for binary formats or bytecode.

The endianess parameter (e.g., bytecode.LittleEndian) is stored in scope.

It registers default events when add_default_events is true.

The parser must implement byteParsing.ParserInterface.

func NewStringEngine

func NewStringEngine(
	generator_res_type int,
	pipeline []string,
	add_default_events bool,
	parser stringParsing.ParserInterface,
	colorEnable bool,
	context context.Context,
) *engine.StringEngine

NewStringEngine creates a ready-to-use string-based engine. Parameters:

generator_res_type – core.StringResType (usually) for text generation.
pipeline – ordered list of generation points (e.g., []string{"pre","main"}).
add_default_events – if true, registers standard parsing and call events.
parser – an implementation of stringParsing.ParserInterface.

Returns a StringEngine with empty command map and initialized UEP.

Types

type EngineBuilder

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

EngineBuilder is a fluent builder for constructing universal engines. It allows to configure pipeline stages, event handling, logging, custom parsers, scope variables, and byte order before calling Build(). Use NewEngineBuilder to create a builder instance.

func NewEngineBuilder

func NewEngineBuilder(engineType int) *EngineBuilder

NewEngineBuilder creates a new EngineBuilder for the given engine type. engineType must be either ByteEngineType or StringEngineType. Defaults: pipeline = []string{"main"}, default events enabled, endianess = bytecode.LittleEndian, empty scope. Example:

builder := lc.NewEngineBuilder(lc.StringEngineType).
            WithPipeline([]string{"pre","main"}).
            WithStringParser(myParser)

func (*EngineBuilder) Build

func (b *EngineBuilder) Build() (*EngineUniversal, error)

Build constructs and returns an EngineUniversal or an error if required components are missing (e.g., a string parser for a StringEngine). The returned engineUniversal can process strings or bytes depending on its type and provides methods to register commands.

func (*EngineBuilder) WithByteParser

func (b *EngineBuilder) WithByteParser(parser byteParsing.ParserInterface) *EngineBuilder

func (*EngineBuilder) WithColors

func (b *EngineBuilder) WithColors() *EngineBuilder

func (*EngineBuilder) WithContext

func (b *EngineBuilder) WithContext(context context.Context) *EngineBuilder

func (*EngineBuilder) WithDefaultEvents

func (b *EngineBuilder) WithDefaultEvents(add bool) *EngineBuilder

func (*EngineBuilder) WithEndianess

func (b *EngineBuilder) WithEndianess(endianess int) *EngineBuilder

func (*EngineBuilder) WithLogger

func (b *EngineBuilder) WithLogger(logger *core.Logger) *EngineBuilder

func (*EngineBuilder) WithPipeline

func (b *EngineBuilder) WithPipeline(pipeline []string) *EngineBuilder

func (*EngineBuilder) WithScope

func (b *EngineBuilder) WithScope(scope core.ScopeType) *EngineBuilder

func (*EngineBuilder) WithStringParser

func (b *EngineBuilder) WithStringParser(parser stringParsing.ParserInterface) *EngineBuilder

type EngineUniversal

type EngineUniversal struct {
	Type         int
	StringEngine *engine.StringEngine
	ByteEngine   *engine.ByteEngine

	Context context.Context
	// contains filtered or unexported fields
}

func (*EngineUniversal) GetUEP

func (*EngineUniversal) NewCommandByte

func (e *EngineUniversal) NewCommandByte(
	opcode int, handler core.CommandType[engine.ByteEngine, byteParsing.ParsedBytes], name string,
	autoByecodeIdxShift bool,
) error

NewCommandByte registers a bytecode command identified by an opcode. If opcode == -1, the engine automatically assigns the next available opcode. handler receives (*ByteEngine, ParsedBytes).

func (*EngineUniversal) NewCommandString

func (e *EngineUniversal) NewCommandString(
	cmdSwitch string, handler core.CommandType[engine.StringEngine, stringParsing.ParsedNode], doc string,
) error

NewCommandString registers a text-based command in a StringEngine. cmdSwitch is the command name (e.g., "print"). handler must have signature func([]interface{}) error where arguments are (*StringEngine, ParsedNode). doc is an optional documentation string.

func (*EngineUniversal) ProcessBytes

func (e *EngineUniversal) ProcessBytes(input []byte) error

ProcessBytes feeds a byte slice into the engine (ByteEngineType only). The input is passed via scope under key "input_[]byte", then parsed and processed.

func (*EngineUniversal) ProcessBytesWithCtx

func (e *EngineUniversal) ProcessBytesWithCtx(input []byte, ctx context.Context) error

func (*EngineUniversal) ProcessString

func (e *EngineUniversal) ProcessString(input string) error

ProcessString feeds a string input into the engine. It works only for engines of type StringEngineType; otherwise returns an error. Internally triggers the parse and call events, executing registered handlers.

func (*EngineUniversal) ProcessStringWithCtx

func (e *EngineUniversal) ProcessStringWithCtx(input string, ctx context.Context) error

Directories

Path Synopsis
tooling

Jump to

Keyboard shortcuts

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