SNAPKITTYWEST's picture
push from SNAPKITTYWEST/sovereign-ide
ffc07fb verified
Raw History Blame Contribute Delete
7.01 kB
! Layer 5 β€” Sovereign IDE Syntax Highlighting
! Query compiler + theme mapping
! Maps to: snapkitty-resonance-bridge token stream structure
MODULE sovereign_syntax
USE iso_c_binding
USE sovereign_runtime, ONLY: runtime_panic, str_intern
USE sovereign_parser, ONLY: parser_ctx_t, cst_node_t
IMPLICIT NONE
PRIVATE
! ── Color IDs (theme slots) ───────────────────────────────────────────────
INTEGER, PARAMETER :: COLOR_DEFAULT = 0
INTEGER, PARAMETER :: COLOR_KEYWORD = 1
INTEGER, PARAMETER :: COLOR_IDENTIFIER = 2
INTEGER, PARAMETER :: COLOR_STRING = 3
INTEGER, PARAMETER :: COLOR_NUMBER = 4
INTEGER, PARAMETER :: COLOR_COMMENT = 5
INTEGER, PARAMETER :: COLOR_OPERATOR = 6
INTEGER, PARAMETER :: COLOR_TYPE = 7
INTEGER, PARAMETER :: COLOR_FUNCTION = 8
INTEGER, PARAMETER :: COLOR_ERROR = 9
INTEGER, PARAMETER :: N_COLORS = 10
! ── Theme ─────────────────────────────────────────────────────────────────
! RGBA packed as 0xRRGGBBAA
TYPE :: theme_t
INTEGER(C_INT32_T) :: colors(N_COLORS)
LOGICAL :: worm_sealed = .FALSE.
END TYPE theme_t
! ── Highlight span ────────────────────────────────────────────────────────
INTEGER, PARAMETER :: MAX_SPANS = 131072
TYPE :: span_t
INTEGER :: start_byte = 0
INTEGER :: end_byte = 0
INTEGER :: color_id = COLOR_DEFAULT
END TYPE span_t
TYPE :: span_list_t
TYPE(span_t) :: spans(MAX_SPANS)
INTEGER :: count = 0
END TYPE span_list_t
! ── Query ─────────────────────────────────────────────────────────────────
INTEGER, PARAMETER :: MAX_QUERY_PATTERNS = 256
TYPE :: query_pattern_t
INTEGER(C_INT32_T) :: node_kind_id = 0
INTEGER :: color_id = COLOR_DEFAULT
END TYPE query_pattern_t
TYPE :: query_t
TYPE(query_pattern_t) :: patterns(MAX_QUERY_PATTERNS)
INTEGER :: pattern_count = 0
END TYPE query_t
PUBLIC :: syntax_init
PUBLIC :: syntax_load_theme
PUBLIC :: syntax_highlight
PUBLIC :: syntax_highlight_incremental
PUBLIC :: theme_default_sovereign_dark
CONTAINS
! ---------------------------------------------------------------------------
SUBROUTINE syntax_init()
WRITE(*,'(A)') '[syntax] init'
END SUBROUTINE syntax_init
! ---------------------------------------------------------------------------
! Load a theme; WORM-seal after load
SUBROUTINE syntax_load_theme(theme, path)
TYPE(theme_t), INTENT(INOUT) :: theme
CHARACTER(LEN=*), INTENT(IN) :: path
! TODO: parse theme file (JSON/TOML)
CALL theme_default_sovereign_dark(theme)
theme%worm_sealed = .TRUE.
WRITE(*,'(A,A)') '[syntax] theme loaded from ', TRIM(path)
END SUBROUTINE syntax_load_theme
! ---------------------------------------------------------------------------
! Sovereign dark theme β€” matches bob-ide color palette
SUBROUTINE theme_default_sovereign_dark(theme)
TYPE(theme_t), INTENT(INOUT) :: theme
theme%colors(COLOR_DEFAULT+1) = INT(Z'D4D4D4FF', C_INT32_T) ! #D4D4D4
theme%colors(COLOR_KEYWORD+1) = INT(Z'569CD6FF', C_INT32_T) ! #569CD6
theme%colors(COLOR_IDENTIFIER+1) = INT(Z'9CDCFEFF', C_INT32_T) ! #9CDCFE
theme%colors(COLOR_STRING+1) = INT(Z'CE9178FF', C_INT32_T) ! #CE9178
theme%colors(COLOR_NUMBER+1) = INT(Z'B5CEA8FF', C_INT32_T) ! #B5CEA8
theme%colors(COLOR_COMMENT+1) = INT(Z'6A9955FF', C_INT32_T) ! #6A9955
theme%colors(COLOR_OPERATOR+1) = INT(Z'D4D4D4FF', C_INT32_T)
theme%colors(COLOR_TYPE+1) = INT(Z'4EC9B0FF', C_INT32_T) ! #4EC9B0
theme%colors(COLOR_FUNCTION+1) = INT(Z'DCDCAAFF', C_INT32_T) ! #DCDCAA
theme%colors(COLOR_ERROR+1) = INT(Z'F44747FF', C_INT32_T) ! #F44747
theme%worm_sealed = .FALSE.
END SUBROUTINE theme_default_sovereign_dark
! ---------------------------------------------------------------------------
! Full highlight pass over entire CST
SUBROUTINE syntax_highlight(ctx, spans, query)
TYPE(parser_ctx_t), INTENT(IN) :: ctx
TYPE(span_list_t), INTENT(INOUT) :: spans
TYPE(query_t), INTENT(IN) :: query
spans%count = 0
CALL highlight_node(ctx, ctx%root, spans, query)
WRITE(*,'(A,I0,A)') '[syntax] highlight: ', spans%count, ' spans'
END SUBROUTINE syntax_highlight
! ---------------------------------------------------------------------------
! Incremental highlight β€” only reprocess changed CST subtree
SUBROUTINE syntax_highlight_incremental(ctx, spans, query, from_node)
TYPE(parser_ctx_t), INTENT(IN) :: ctx
TYPE(span_list_t), INTENT(INOUT) :: spans
TYPE(query_t), INTENT(IN) :: query
INTEGER, INTENT(IN) :: from_node
! TODO: invalidate spans overlapping from_node range, re-run from there
CALL highlight_node(ctx, from_node, spans, query)
END SUBROUTINE syntax_highlight_incremental
! ── Internal ──────────────────────────────────────────────────────────────
RECURSIVE SUBROUTINE highlight_node(ctx, idx, spans, query)
TYPE(parser_ctx_t), INTENT(IN) :: ctx
INTEGER, INTENT(IN) :: idx
TYPE(span_list_t), INTENT(INOUT) :: spans
TYPE(query_t), INTENT(IN) :: query
INTEGER :: i, color, child
IF (idx == 0) RETURN
! Match node kind against query patterns
color = COLOR_DEFAULT
IF (ctx%nodes(idx)%is_error) THEN
color = COLOR_ERROR
ELSE
DO i = 1, query%pattern_count
IF (query%patterns(i)%node_kind_id == ctx%nodes(idx)%kind) THEN
color = query%patterns(i)%color_id
EXIT
END IF
END DO
END IF
! Emit span if leaf
IF (ctx%nodes(idx)%n_children == 0) THEN
IF (spans%count < MAX_SPANS) THEN
spans%count = spans%count + 1
spans%spans(spans%count)%start_byte = ctx%nodes(idx)%start_byte
spans%spans(spans%count)%end_byte = ctx%nodes(idx)%end_byte
spans%spans(spans%count)%color_id = color
END IF
RETURN
END IF
! Recurse into children
DO i = 1, ctx%nodes(idx)%n_children
child = ctx%nodes(idx)%children(i)
CALL highlight_node(ctx, child, spans, query)
END DO
END SUBROUTINE highlight_node
END MODULE sovereign_syntax