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;
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.

View file

@ -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;
}