so much meaningless stuff :]

This commit is contained in:
mehbark 2023-04-17 19:52:04 -04:00
parent 0f348a7e07
commit 83dc103386
2 changed files with 105 additions and 28 deletions

View file

@ -35,19 +35,21 @@ html {
display: grid; display: grid;
width: 50%; width: 50%;
grid-template-areas: "ops stack" "states states"; grid-template-areas: "ops stack" "states states";
grid-template-rows: max-content; grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%;
} }
/* .ops, .ops,
.states { .stack {
width: 50vw; overflow: scroll;
} */ width: 100%;
}
.ops { .ops {
/* position: fixed; */ /* position: fixed; */
/* top: 0; /* top: 0;
left: 50%; */ left: 50%; */
min-height: 25vh; /* height: 100%; */
margin-bottom: 0; margin-bottom: 0;
background-color: var(--bg); background-color: var(--bg);
border: 1px solid var(--fg); border: 1px solid var(--fg);
@ -66,6 +68,7 @@ html {
border-bottom: 1px solid var(--fg); border-bottom: 1px solid var(--fg);
/* margin: 5px; */ /* margin: 5px; */
padding-left: 5px; padding-left: 5px;
background-color: var(--bg);
} }
/* .state > * { /* .state > * {
@ -79,9 +82,9 @@ html {
padding: 5px; padding: 5px;
} }
.stack::before { /* .stack::before {
content: "Stack: "; content: "Stack: ";
} } */
/* later i can do .op.active and .state.active if necessary */ /* later i can do .op.active and .state.active if necessary */
.active { .active {
@ -92,15 +95,24 @@ html {
background-color: var(--accent); background-color: var(--accent);
} }
.jumped-from {
backdrop-filter: brightness(1.8);
}
.op { .op {
display: flex; display: flex;
white-space: pre; white-space: pre;
overflow: clip;
} }
.output { .output {
display: flex; display: flex;
} }
.just-popped {
backdrop-filter: hue-rotate(180deg);
}
/* https://www.joshwcomeau.com/css/custom-css-reset/ */ /* https://www.joshwcomeau.com/css/custom-css-reset/ */
/* /*
1. Use a more-intuitive box-sizing model. 1. Use a more-intuitive box-sizing model.

View file

@ -15,6 +15,8 @@ export default function App() {
let [activeStateIdx, setActiveStateIdx] = useState(0); let [activeStateIdx, setActiveStateIdx] = useState(0);
let parsed = somes(input.split(/[^a-z0-9-]+/).map(parse_op)); let parsed = somes(input.split(/[^a-z0-9-]+/).map(parse_op));
let states = steps(INITIAL_STATE, parsed); let states = steps(INITIAL_STATE, parsed);
let state = states[activeStateIdx] ?? INITIAL_STATE;
return ( return (
<> <>
<TextArea <TextArea
@ -38,11 +40,11 @@ type Op =
<div className="info"> <div className="info">
<Ops <Ops
parsed={parsed} parsed={parsed}
ip={states[activeStateIdx]?.ip ?? 0} state={state}
// // hack // // hack
// top={document.getElementById("input")?.clientHeight ?? 0} // top={document.getElementById("input")?.clientHeight ?? 0}
/> />
<Stack stack={states[activeStateIdx]?.stack ?? []} /> <Stack state={state} just_popped={state.just_popped} />
<States <States
states={states} states={states}
activeStateIdx={activeStateIdx} activeStateIdx={activeStateIdx}
@ -55,18 +57,24 @@ type Op =
function Ops({ function Ops({
parsed, parsed,
ip, state,
}: // top, }: // top,
{ {
parsed: Op[]; parsed: Op[];
ip: number; state: State;
// top: number; // top: number;
}): JSX.Element { }): JSX.Element {
return ( return (
<div <div
className="ops" className="ops"
children={parsed.map((op, i) => ( children={parsed.map((op, i) => (
<Op op={op} highlighted={i == ip} num={i} key={i} /> <Op
op={op}
highlighted={i == state.ip}
jumped_from={i == state.jumped_from}
num={i}
key={i}
/>
))} ))}
// style={{ // style={{
// top: `${top + 5}px`, // top: `${top + 5}px`,
@ -79,15 +87,19 @@ function Op({
op, op,
highlighted, highlighted,
num, num,
jumped_from,
...props ...props
}: { }: {
op: Op; op: Op;
num: number; num: number;
highlighted: boolean; highlighted: boolean;
jumped_from: boolean;
}): JSX.Element { }): JSX.Element {
return ( return (
<div <div
className={`op ${highlighted ? "active" : ""}`} className={`op ${highlighted ? "active" : ""} ${
jumped_from ? "jumped-from" : ""
}`}
key={num} key={num}
{...props} {...props}
> >
@ -146,23 +158,55 @@ function State({
); );
} }
function Stack({ stack, ...props }: { stack: number[] }): JSX.Element { function Stack({
let ns = [...stack]; state,
just_popped,
...props
}: {
state: State;
just_popped?: number[];
}): JSX.Element {
let ns = [...state.stack];
ns.reverse(); ns.reverse();
return ( console.log(just_popped);
<div let children = (just_popped ?? []).map((just_popped, i) => (
className="stack" <StackItem
children={ns.map((item, i) => ( item={just_popped}
<StackItem item={item} key={i} /> key={-(i + 1)}
))} highlighted={false}
{...props} just_popped={true}
/> />
); ));
ns.map((item, i) => (
<StackItem
item={item}
key={i}
highlighted={
(state.just_pushed && i == 0) || (state.just_swapped && i < 2)
}
/>
)).forEach(child => children.push(child));
return <div className="stack" children={children} {...props} />;
} }
function StackItem({ item, ...props }: { item: number }): JSX.Element { function StackItem({
item,
highlighted = false,
just_popped = false,
...props
}: {
item: number;
highlighted: boolean;
just_popped?: boolean;
}): JSX.Element {
return ( return (
<div className="stack-item" {...props}> <div
className={`stack-item ${highlighted ? "active" : ""} ${
just_popped ? "just-popped" : ""
}`}
{...props}
>
{item} {item}
</div> </div>
); );
@ -252,12 +296,19 @@ type State = {
ip: number; ip: number;
stack: number[]; stack: number[];
output: number[]; output: number[];
jumped_from: Option<number>;
just_pushed: boolean;
just_swapped: boolean;
just_popped?: number[];
}; };
const INITIAL_STATE: State = { const INITIAL_STATE: State = {
ip: 0, ip: 0,
stack: [], stack: [],
output: [], output: [],
jumped_from: undefined,
just_pushed: false,
just_swapped: false,
}; };
function steps(state: State, ops: Op[], limit = 300, num_steps = 0): State[] { function steps(state: State, ops: Op[], limit = 300, num_steps = 0): State[] {
@ -273,7 +324,11 @@ function steps(state: State, ops: Op[], limit = 300, num_steps = 0): State[] {
// all but jmp advance the ip by one // all but jmp advance the ip by one
// cmp: lt => -1, eq => 0, gt => 1 // cmp: lt => -1, eq => 0, gt => 1
function step(state: State, op: Op): State { function step(state: State, op: Op): State {
let ns = JSON.parse(JSON.stringify(state)); let ns = JSON.parse(JSON.stringify(state)) as State;
ns.jumped_from = ns.ip;
ns.just_pushed = false;
ns.just_swapped = false;
ns.just_popped = undefined;
ns.ip++; ns.ip++;
function binary_op( function binary_op(
@ -287,7 +342,6 @@ function step(state: State, op: Op): State {
if (typeof op == "number") { if (typeof op == "number") {
ns.stack.push(op); ns.stack.push(op);
return ns;
} }
switch (op) { switch (op) {
@ -312,6 +366,7 @@ function step(state: State, op: Op): State {
} }
case "jmp": case "jmp":
ns.ip--; ns.ip--;
// ns.jumped_from = ns.ip;
ns.ip += ns.stack.pop() ?? 1; ns.ip += ns.stack.pop() ?? 1;
break; break;
case "dup": { case "dup": {
@ -335,11 +390,21 @@ function step(state: State, op: Op): State {
if (typeof a == "undefined" || typeof b == "undefined") { if (typeof a == "undefined" || typeof b == "undefined") {
break; break;
} }
ns.just_swapped = true;
ns.stack.push(a, b); ns.stack.push(a, b);
break; break;
} }
} }
if (ns.stack.length > state.stack.length) {
ns.just_pushed = true;
} else if (ns.stack.length < state.stack.length) {
ns.just_popped = state.stack.slice(ns.stack.length - 1).reverse();
if (state.stack.length - ns.stack.length == 1) {
ns.just_pushed = true;
}
}
return ns; return ns;
} }