parsley-core-1.8.0.0: src/ghc-8.10+/Parsley/Internal/Backend/Machine/PosOps.hs
{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NumericUnderscores #-}
{-|
Module : Parsley.Internal.Backend.Machine.PosOps
Description : Collection of platform dependent position operations
License : BSD-3-Clause
Maintainer : Jamie Willis
Stability : experimental
This module contains the implementations of updates on positions: these depend on the number of
bits in a word, or if the @full-width-positions@ flag was set on the @parsley-core@ library.
@since 1.8.0.0
-}
module Parsley.Internal.Backend.Machine.PosOps (module Parsley.Internal.Backend.Machine.PosOps) where
#include "MachDeps.h"
#if WORD_SIZE_IN_BITS < 64
#define FULL_WIDTH_POSITIONS
#endif
import Parsley.Internal.Backend.Machine.Types.Base (Pos)
import Parsley.Internal.Common (Code)
import GHC.Exts (Int(..))
import GHC.Prim (plusWord#, and#, or#, word2Int#,
#ifdef FULL_WIDTH_POSITIONS
minusWord#
#else
uncheckedShiftRL#
#endif
)
{-|
Given a position and a character, returns the representation of the updated position.
@since 1.8.0.0
-}
updatePos :: Code Pos -> Code Char -> Code Pos
updatePos pos c = [||updatePos# $$pos $$c||]
{-|
The initial position used by the parser. This is some representation of (1, 1).
@since 1.8.0.0
-}
initPos :: Code Pos
{-# INLINEABLE updatePos# #-}
{-|
Updates a given position assuming the given character was read. Tab characters are aligned to the
nearest 4th space boundary.
@since 1.8.0.0
-}
updatePos# :: Pos -> Char -> Pos
{-|
Given the opaque representation of a position, extracts the line number out of it.
@since 1.8.0.0
-}
extractLine :: Code Pos -> Code Int
{-|
Given the opaque representation of a position, extracts the column number out of it.
@since 1.8.0.0
-}
extractCol :: Code Pos -> Code Int
#ifndef FULL_WIDTH_POSITIONS
initPos = [|| 0x00000001_00000001## ||]
updatePos# pos '\n' = (pos `and#` 0xffffffff_00000000##) `plusWord#` 0x00000001_00000001##
updatePos# pos '\t' = ((pos `plusWord#` 0x00000000_00000003##) `and#` 0xffffffff_fffffffc##) `or#` 0x00000000_00000001##
updatePos# pos _ = pos `plusWord#` 0x00000000_00000001##
extractLine qpos = [||I# (word2Int# ($$qpos `uncheckedShiftRL#` 32#))||]
extractCol qpos = [||I# (word2Int# ($$qpos `and#` 0x00000000_ffffffff##))||]
#else
initPos = [|| (# 1##, 1## #) ||]
updatePos# (# line, _ #) '\n' = (# line `plusWord#` 1##, 1## #)
updatePos# (# line, col #) '\t' = (# line, ((col `plusWord#` 3##) `and#` (0## `minusWord#` 4##)) `or#` 1## #) -- nearest tab boundary `c + (4 - (c - 1) % 4)`
updatePos# (# line, col #) _ = (# line, col `plusWord#` 1## #)
extractLine qpos = [|| case $$qpos of (# line, _ #) -> I# (word2Int# line) ||]
extractCol qpos = [|| case $$qpos of (# _, col #) -> I# (word2Int# col) ||]
#endif