import { For, Show } from 'solid-js'; import type { JSX } from 'solid-js'; import type { CodePointSpan } from 'source-region'; import type { ConcreteError, ConcreteErrorNode, ConcreteInfo, List, ListItem, Expr as SyntaxExpr, } from '../syntax'; import type { PartialConcreteSyntax } from '../parser'; import { Expr } from '../syntax'; import { errorDetail, errorTitle, spanLabel } from './format'; import type { HoverTarget } from './types'; type PartialExpr = SyntaxExpr; type PartialList = List; type PartialListItem = ListItem; export function StructureTree(props: { program: PartialConcreteSyntax; isValid: boolean; errorCount: number; onHover: (target: HoverTarget | undefined) => void; }) { return (
program {props.isValid ? "valid" : "invalid"} · {props.program.expressions.length} expressions · {props.errorCount} errors
{(error) => }
{(expr, index) => ( )}
); } function ExprView(props: { expr: PartialExpr; label: string; onHover: (target: HoverTarget | undefined) => void; }) { switch (props.expr.tag) { case "number": case "identifier": return (
{props.expr.tag} {Expr.show(props.expr)}
); case "error-number": case "error-identifier": case "error-expression": return (
{props.expr.tag} {spanLabel(props.expr.span)}
); case "list": return ; } } function ListView(props: { list: PartialList; label: string; onHover: (target: HoverTarget | undefined) => void; }) { return (
{listLabel(props.list.open.tag)} {props.list.items.length} items · {delimiterLabel(props.list)}
{(close) => }
{(error) => }
{(item, index) => ( )}
); } function ListItemView(props: { item: PartialListItem; label: string; onHover: (target: HoverTarget | undefined) => void; }) { if (props.item.tag === "error-list-separator") { return (
error-list-separator {spanLabel(props.item.span)}
); } return ; } function ConcreteErrorView(props: { error: ConcreteError; label: string; onHover: (target: HoverTarget | undefined) => void; }) { return (
{(node, index) => ( )}
); } function ConcreteErrorNodeView(props: { node: ConcreteErrorNode; label: string; onHover: (target: HoverTarget | undefined) => void; }) { return (
{errorTitle(props.node.error)}
{errorDetail(props.node.error)}
{(span) => }
); } function SpanChip(props: { label: string; span: CodePointSpan; onHover: (target: HoverTarget | undefined) => void; }) { return ( ); } function HoverBlock(props: { class: string; label: string; span: CodePointSpan; onHover: (target: HoverTarget | undefined) => void; children: JSX.Element; }) { return (
props.onHover({ label: props.label, span: props.span })} onMouseLeave={() => props.onHover(undefined)} > {props.children}
); } function listLabel(tag: string): string { return tag === "open-bracket" ? "square-list" : "round-list"; } function delimiterLabel(list: PartialList): string { return list.close ? `${list.open.tag} / ${list.close.tag}` : `${list.open.tag} / missing close`; }