so much meaningless stuff :]
This commit is contained in:
parent
0f348a7e07
commit
83dc103386
2 changed files with 105 additions and 28 deletions
28
src/App.css
28
src/App.css
|
@ -35,19 +35,21 @@ html {
|
|||
display: grid;
|
||||
width: 50%;
|
||||
grid-template-areas: "ops stack" "states states";
|
||||
grid-template-rows: max-content;
|
||||
grid-template-columns: 50% 50%;
|
||||
grid-template-rows: 50% 50%;
|
||||
}
|
||||
|
||||
/* .ops,
|
||||
.states {
|
||||
width: 50vw;
|
||||
} */
|
||||
.ops,
|
||||
.stack {
|
||||
overflow: scroll;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ops {
|
||||
/* position: fixed; */
|
||||
/* top: 0;
|
||||
left: 50%; */
|
||||
min-height: 25vh;
|
||||
/* height: 100%; */
|
||||
margin-bottom: 0;
|
||||
background-color: var(--bg);
|
||||
border: 1px solid var(--fg);
|
||||
|
@ -66,6 +68,7 @@ html {
|
|||
border-bottom: 1px solid var(--fg);
|
||||
/* margin: 5px; */
|
||||
padding-left: 5px;
|
||||
background-color: var(--bg);
|
||||
}
|
||||
|
||||
/* .state > * {
|
||||
|
@ -79,9 +82,9 @@ html {
|
|||
padding: 5px;
|
||||
}
|
||||
|
||||
.stack::before {
|
||||
/* .stack::before {
|
||||
content: "Stack: ";
|
||||
}
|
||||
} */
|
||||
|
||||
/* later i can do .op.active and .state.active if necessary */
|
||||
.active {
|
||||
|
@ -92,15 +95,24 @@ html {
|
|||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
.jumped-from {
|
||||
backdrop-filter: brightness(1.8);
|
||||
}
|
||||
|
||||
.op {
|
||||
display: flex;
|
||||
white-space: pre;
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
.output {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.just-popped {
|
||||
backdrop-filter: hue-rotate(180deg);
|
||||
}
|
||||
|
||||
/* https://www.joshwcomeau.com/css/custom-css-reset/ */
|
||||
/*
|
||||
1. Use a more-intuitive box-sizing model.
|
||||
|
|
105
src/App.tsx
105
src/App.tsx
|
@ -15,6 +15,8 @@ export default function App() {
|
|||
let [activeStateIdx, setActiveStateIdx] = useState(0);
|
||||
let parsed = somes(input.split(/[^a-z0-9-]+/).map(parse_op));
|
||||
let states = steps(INITIAL_STATE, parsed);
|
||||
let state = states[activeStateIdx] ?? INITIAL_STATE;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TextArea
|
||||
|
@ -38,11 +40,11 @@ type Op =
|
|||
<div className="info">
|
||||
<Ops
|
||||
parsed={parsed}
|
||||
ip={states[activeStateIdx]?.ip ?? 0}
|
||||
state={state}
|
||||
// // hack
|
||||
// top={document.getElementById("input")?.clientHeight ?? 0}
|
||||
/>
|
||||
<Stack stack={states[activeStateIdx]?.stack ?? []} />
|
||||
<Stack state={state} just_popped={state.just_popped} />
|
||||
<States
|
||||
states={states}
|
||||
activeStateIdx={activeStateIdx}
|
||||
|
@ -55,18 +57,24 @@ type Op =
|
|||
|
||||
function Ops({
|
||||
parsed,
|
||||
ip,
|
||||
state,
|
||||
}: // top,
|
||||
{
|
||||
parsed: Op[];
|
||||
ip: number;
|
||||
state: State;
|
||||
// top: number;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className="ops"
|
||||
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={{
|
||||
// top: `${top + 5}px`,
|
||||
|
@ -79,15 +87,19 @@ function Op({
|
|||
op,
|
||||
highlighted,
|
||||
num,
|
||||
jumped_from,
|
||||
...props
|
||||
}: {
|
||||
op: Op;
|
||||
num: number;
|
||||
highlighted: boolean;
|
||||
jumped_from: boolean;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={`op ${highlighted ? "active" : ""}`}
|
||||
className={`op ${highlighted ? "active" : ""} ${
|
||||
jumped_from ? "jumped-from" : ""
|
||||
}`}
|
||||
key={num}
|
||||
{...props}
|
||||
>
|
||||
|
@ -146,23 +158,55 @@ function State({
|
|||
);
|
||||
}
|
||||
|
||||
function Stack({ stack, ...props }: { stack: number[] }): JSX.Element {
|
||||
let ns = [...stack];
|
||||
function Stack({
|
||||
state,
|
||||
just_popped,
|
||||
...props
|
||||
}: {
|
||||
state: State;
|
||||
just_popped?: number[];
|
||||
}): JSX.Element {
|
||||
let ns = [...state.stack];
|
||||
ns.reverse();
|
||||
return (
|
||||
<div
|
||||
className="stack"
|
||||
children={ns.map((item, i) => (
|
||||
<StackItem item={item} key={i} />
|
||||
))}
|
||||
{...props}
|
||||
console.log(just_popped);
|
||||
let children = (just_popped ?? []).map((just_popped, i) => (
|
||||
<StackItem
|
||||
item={just_popped}
|
||||
key={-(i + 1)}
|
||||
highlighted={false}
|
||||
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 (
|
||||
<div className="stack-item" {...props}>
|
||||
<div
|
||||
className={`stack-item ${highlighted ? "active" : ""} ${
|
||||
just_popped ? "just-popped" : ""
|
||||
}`}
|
||||
{...props}
|
||||
>
|
||||
{item}
|
||||
</div>
|
||||
);
|
||||
|
@ -252,12 +296,19 @@ type State = {
|
|||
ip: number;
|
||||
stack: number[];
|
||||
output: number[];
|
||||
jumped_from: Option<number>;
|
||||
just_pushed: boolean;
|
||||
just_swapped: boolean;
|
||||
just_popped?: number[];
|
||||
};
|
||||
|
||||
const INITIAL_STATE: State = {
|
||||
ip: 0,
|
||||
stack: [],
|
||||
output: [],
|
||||
jumped_from: undefined,
|
||||
just_pushed: false,
|
||||
just_swapped: false,
|
||||
};
|
||||
|
||||
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
|
||||
// cmp: lt => -1, eq => 0, gt => 1
|
||||
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++;
|
||||
|
||||
function binary_op(
|
||||
|
@ -287,7 +342,6 @@ function step(state: State, op: Op): State {
|
|||
|
||||
if (typeof op == "number") {
|
||||
ns.stack.push(op);
|
||||
return ns;
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
|
@ -312,6 +366,7 @@ function step(state: State, op: Op): State {
|
|||
}
|
||||
case "jmp":
|
||||
ns.ip--;
|
||||
// ns.jumped_from = ns.ip;
|
||||
ns.ip += ns.stack.pop() ?? 1;
|
||||
break;
|
||||
case "dup": {
|
||||
|
@ -335,11 +390,21 @@ function step(state: State, op: Op): State {
|
|||
if (typeof a == "undefined" || typeof b == "undefined") {
|
||||
break;
|
||||
}
|
||||
ns.just_swapped = true;
|
||||
ns.stack.push(a, b);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue