mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Basis support for inspecting types
This commit is contained in:
parent
8b7823a237
commit
9e055dcf53
8 changed files with 753 additions and 7 deletions
53
crates/compiler/checkmate/www/src/components/FileInput.tsx
Normal file
53
crates/compiler/checkmate/www/src/components/FileInput.tsx
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { AllEvents } from "../schema";
|
||||
|
||||
export type EventsOk = {
|
||||
kind: "ok";
|
||||
events: AllEvents;
|
||||
};
|
||||
|
||||
export type EventsErr = {
|
||||
kind: "err";
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type LoadedEvents = EventsOk | EventsErr;
|
||||
|
||||
interface FileInputProps {
|
||||
setResult(result: LoadedEvents): void;
|
||||
}
|
||||
|
||||
export default function FileInput({ setResult }: FileInputProps) {
|
||||
async function setFile(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
e.preventDefault();
|
||||
const files = e.target.files;
|
||||
if (!files) {
|
||||
setResult({ kind: "err", error: "Please choose a checkmate file." });
|
||||
return;
|
||||
}
|
||||
const file = files[0];
|
||||
const buf = await file.arrayBuffer();
|
||||
try {
|
||||
const events: AllEvents = JSON.parse(new TextDecoder().decode(buf));
|
||||
setResult({ kind: "ok", events });
|
||||
} catch (e) {
|
||||
setResult({ kind: "err", error: "Invalid checkmate file." });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label htmlFor="small-file-input" className="sr-only">
|
||||
Choose file
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
name="small-file-input"
|
||||
id="small-file-input"
|
||||
onChange={(e) => setFile(e)}
|
||||
className="block w-full border border-gray-200 shadow-sm rounded-md text-sm
|
||||
file:bg-roc-purple-bg file:border-0 file:mr-4 file:py-2 file:px-4"
|
||||
></input>
|
||||
</div>
|
||||
);
|
||||
}
|
107
crates/compiler/checkmate/www/src/components/Ui.tsx
Normal file
107
crates/compiler/checkmate/www/src/components/Ui.tsx
Normal file
|
@ -0,0 +1,107 @@
|
|||
import React from "react";
|
||||
import { AllEvents, Event, UnificationMode } from "../schema";
|
||||
import { Refine } from "../utils/refine";
|
||||
import clsx from "clsx";
|
||||
|
||||
interface UiProps {
|
||||
events: AllEvents;
|
||||
}
|
||||
|
||||
export default function Ui({ events }: UiProps): JSX.Element {
|
||||
return (
|
||||
<div className="font-mono">
|
||||
<EventList root events={events}></EventList>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface EventListProps {
|
||||
events: Event[];
|
||||
root?: boolean;
|
||||
}
|
||||
|
||||
function EventList({ events, root }: EventListProps): JSX.Element {
|
||||
return (
|
||||
<ul className={clsx(root ? "ml-2 mt-4" : "ml-[1.5em]", "relative")}>
|
||||
{events.map((event, i) => (
|
||||
<li key={i} className="mt-2">
|
||||
<OneEvent event={event} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
interface OneEventProps {
|
||||
event: Event;
|
||||
}
|
||||
|
||||
function OneEvent({ event }: OneEventProps): JSX.Element {
|
||||
switch (event.type) {
|
||||
case "Unification":
|
||||
return <Unification event={event} />;
|
||||
case "VariableUnified":
|
||||
return <></>;
|
||||
case "VariableSetDescriptor":
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
|
||||
const DROPDOWN_CLOSED = "▶";
|
||||
const DROPDOWN_OPEN = "▼";
|
||||
|
||||
const UN_UNKNOWN = "❔";
|
||||
const UN_SUCCESS = "✅";
|
||||
const UN_FAILURE = "❌";
|
||||
|
||||
function Unification({
|
||||
event,
|
||||
}: {
|
||||
event: Refine<Event, "Unification">;
|
||||
}): JSX.Element {
|
||||
const { left, right, mode, subevents, success } = event;
|
||||
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
const result = success ? UN_SUCCESS : UN_FAILURE;
|
||||
const modeIcon = <UnificationModeIcon mode={mode} />;
|
||||
const dropdownIcon = isOpen ? DROPDOWN_OPEN : DROPDOWN_CLOSED;
|
||||
|
||||
const headLineIcon = isOpen ? UN_UNKNOWN : result;
|
||||
|
||||
const headLine = (
|
||||
<button onClick={() => setIsOpen(!isOpen)} className="w-full text-left">
|
||||
<span className="text-slate-400 mr-2">{dropdownIcon}</span>
|
||||
{headLineIcon} {left} {modeIcon} {right}
|
||||
</button>
|
||||
);
|
||||
|
||||
if (!isOpen) {
|
||||
return <div className="opacity-60">{headLine}</div>;
|
||||
} else {
|
||||
const dropdownTransparent = (
|
||||
<span className="text-transparent mr-2">{dropdownIcon}</span>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<div>{headLine}</div>
|
||||
<EventList events={subevents} />
|
||||
<div className="mt-2">
|
||||
{dropdownTransparent}
|
||||
{result} {left} {modeIcon} {right}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function UnificationModeIcon({ mode }: { mode: UnificationMode }): JSX.Element {
|
||||
switch (mode.type) {
|
||||
case "Eq":
|
||||
return <>~</>;
|
||||
case "Present":
|
||||
return <>+=</>;
|
||||
case "LambdaSetSpecialization":
|
||||
return <>|~|</>;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue