smirk-0.1.0.0: src/Smirk/Core/Bytecode.hs
{-# LANGUAGE DeriveGeneric #-}
{- |
Module : Smirk.Core.Bytecode
Description : Virtual machine bytecode instruction set and compiled program structures
Copyright : (c) Nadia Yvette Chambers, 2026
License : Apache-2.0
Defines the low-level virtual machine bytecode instruction set ('Opcode')
used by the Pike-style non-backtracking / thread-stepped VM in 'Smirk.Engine.VM'.
Includes relative jumping, nondeterministic thread branching ('OpSplit'),
capture slot registers ('OpSaveStart', 'OpSaveEnd'), and lookaround subprograms.
-}
module Smirk.Core.Bytecode
( Opcode (..)
, Program
, Regex (..)
) where
import Data.Map.Strict (Map)
import Data.Text (Text)
import Data.Vector (Vector)
import GHC.Generics (Generic)
import Smirk.Core.AST (Anchor, CharClass)
-- | Low-level bytecode instruction for the Smirk regex virtual machine.
data Opcode
= OpChar !Char -- ^ Match a single literal character
| OpClass !CharClass -- ^ Match a character class or set
| OpAnchor !Anchor -- ^ Assert a zero-width anchor condition
| OpSplit !Int !Int -- ^ Fork execution: try relative offset 1, alternative at offset 2
| OpJump !Int -- ^ Unconditional relative jump by specified offset
| OpSaveStart !Int -- ^ Save current input position as start of capture group $n$
| OpSaveEnd !Int -- ^ Save current input position as end of capture group $n$
| OpAssertLookahead !(Vector Opcode) !Bool -- ^ Zero-width lookahead assertion: subprogram and polarity
| OpAssertLookbehind !(Vector Opcode) !Bool -- ^ Zero-width lookbehind assertion: subprogram and polarity
| OpMatchBackRef !Int -- ^ Match dynamic slice previously captured by group $n$
| OpMatch -- ^ Successful match reached; terminate thread
deriving (Eq, Show, Generic)
-- | Compiled bytecode sequence indexed as a contiguous vector.
type Program = Vector Opcode
-- | Complete compiled regular expression ready for VM execution.
data Regex = Regex
{ originalPattern :: !Text -- ^ Original PCRE source pattern string
, program :: !Program -- ^ Compiled bytecode instruction vector
, groupNames :: !(Map Text Int) -- ^ Mapping from named capture groups to 1-based indices
, maxGroupIndex :: !Int -- ^ Highest capture group index allocated in the pattern
} deriving (Eq, Show, Generic)