Skip to content

Commit

Permalink
feat: add basic UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Feb 10, 2024
1 parent 65c6b19 commit 999dff2
Show file tree
Hide file tree
Showing 19 changed files with 204 additions and 20 deletions.
3 changes: 2 additions & 1 deletion apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"react-codemirror2": "^7.3.0",
"react-icons": "^5.0.1",
"sass": "^1.70.0",
"tailwindcss": "^3.4.1"
"tailwindcss": "^3.4.1",
"@ts-c-compiler/compiler": "*"
}
}
1 change: 1 addition & 0 deletions apps/site/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './shallowCompareArrays';
22 changes: 22 additions & 0 deletions apps/site/src/helpers/shallowCompareArrays.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Nullable } from '../types';

export const shallowCompareArrays = <T>(
a: Nullable<readonly T[]>,
b: Nullable<readonly T[]>,
) => {
if (a === b) {
return true;
}

if (!a || !b) {
return false;
}

for (let i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) {
return false;
}
}

return true;
};
1 change: 1 addition & 0 deletions apps/site/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useInstantUpdateEffect';
13 changes: 13 additions & 0 deletions apps/site/src/hooks/useInstantUpdateEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useState } from 'react';
import type { DependencyList } from 'react';

import { shallowCompareArrays } from '../helpers';

export const useInstantUpdateEffect = (fn: VoidFunction, deps: DependencyList) => {
const [prevDeps, setPrevDeps] = useState(deps);

if (prevDeps && !shallowCompareArrays(prevDeps, deps)) {
setPrevDeps(deps);
fn();
}
};
66 changes: 66 additions & 0 deletions apps/site/src/modules/Editor/EditorScreen/EditorScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useRef, useEffect } from 'react';
import { either as E } from 'fp-ts';

import { VGARenderLoopDriver, X86CPU } from '@ts-c-compiler/x86-cpu';

import { useInstantUpdateEffect } from 'hooks';
import { useEditorState } from '../EditorStateProvider';

export const EditorScreen = () => {
const { emulation } = useEditorState();
const screenRef = useRef<HTMLDivElement>(null);
const cpuRef = useRef<X86CPU>();

useEffect(() => {
if (!screenRef.current) {
return;
}

const cpu = new X86CPU();
cpu.attach(VGARenderLoopDriver, {
screenElement: screenRef.current,
});

cpuRef.current = cpu;

return () => {
cpu.release();
};
}, []);

useInstantUpdateEffect(() => {
const cpu = cpuRef.current;

if (!cpu) {
return;
}

switch (emulation.info.state) {
case 'stop':
cpu.halt();
break;

case 'pause':
cpu.freeze();
break;

case 'running': {
if (E.isLeft(emulation.info.result)) {
cpu.halt();
return;
}

cpu.boot(emulation.info.result.right.blob);
break;
}
}
}, [emulation.info.state]);

return (
<div
ref={screenRef}
className="mx-auto block text-center"
style={{ imageRendering: 'pixelated' }}
/>
);
};
1 change: 1 addition & 0 deletions apps/site/src/modules/Editor/EditorScreen/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './EditorScreen';
8 changes: 7 additions & 1 deletion apps/site/src/modules/Editor/EditorSidebar/EditorSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { EditorScreen } from '../EditorScreen';

export const EditorSidebar = () => {
return <div className="p-4" />;
return (
<div className="grid grid-rows-2 p-4">
<EditorScreen />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { useControlStrict } from '@under-control/forms';
import { Buffer } from 'buffer';
import { pipe } from 'fp-ts/function';
import { either as E } from 'fp-ts';
import { useState } from 'react';

import { useControlStrict } from '@under-control/forms';
import constate from 'constate';

import { asm } from '@ts-c-compiler/x86-assembler';
import {
CCompilerArch,
ccompiler,
getX86BootsectorPreloaderBinary,
wrapWithX86BootsectorAsm,
} from '@ts-c-compiler/compiler';

import type { EditorEmulationValue, EditorStateValue } from './types';

const useEditorStateValue = () => {
Expand All @@ -13,14 +23,67 @@ const useEditorStateValue = () => {
const control = useControlStrict<EditorStateValue>({
defaultValue: {
lang: 'c',
code: 'int main() { return 0; }',
code: '#include <stdio.h>\n\nint main() { printf("Hello World!"); return 0; }',
},
});

const {
value: { lang, code },
} = control;

const run = () => {
const result = (() => {
switch (lang) {
case 'nasm':
return pipe(
code,
asm(),
E.map(({ output }) => ({
blob: Buffer.from(output.getBinary()),
})),
);

case 'c':
return pipe(
code,
ccompiler({
arch: CCompilerArch.X86_16,
optimization: {
enabled: true,
},
}),
E.map(compilerResult => wrapWithX86BootsectorAsm(compilerResult.codegen.asm)),
E.chainW(asmRaw =>
pipe(
asmRaw,
asm({
preprocessor: true,
compilerConfig: {
maxPasses: 7,
externalLinkerAddrGenerator: () => 0xff_ff,
},
}),
),
),
E.map(({ output }) => ({
blob: Buffer.from(
getX86BootsectorPreloaderBinary().concat(output.getBinary()),
),
})),
);

default:
throw new Error('Unknown compile lang!');
}
})();

if (E.isLeft(result)) {
console.error(result.left);
}

setEmulation({
state: 'running',
result: 1,
result,
});
};

Expand All @@ -43,7 +106,7 @@ const useEditorStateValue = () => {
return {
control,
emulation: {
state: emulation.state,
info: emulation,
stop,
pause,
run,
Expand Down
9 changes: 8 additions & 1 deletion apps/site/src/modules/Editor/EditorStateProvider/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { either as E } from 'fp-ts';

export type EditorCompileLang = 'nasm' | 'c';

export type EditorStateValue = {
Expand All @@ -9,7 +11,12 @@ type AbstractEmulationState<S extends string, P = {}> = P & {
state: S;
};

type EditorCompileResult = any;
type EditorCompileResult = E.Either<
unknown,
{
blob: Buffer;
}
>;

export type EditorEmulationValue =
| AbstractEmulationState<'stop'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const EditorCompilationToolbar = () => {
<div className="flex justify-center">
<EditorCompileLangDropdown
{...control.bind.path('lang')}
disabled={emulation.state !== 'stop'}
disabled={emulation.info.state !== 'stop'}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useEditorState } from '../EditorStateProvider';
export const EditorEmulationToolbar = () => {
const t = useI18n().pack.header;
const { emulation } = useEditorState();
const { state } = emulation.info;

return (
<ol className="flex flex-row gap-2">
Expand All @@ -15,7 +16,7 @@ export const EditorEmulationToolbar = () => {
color="success"
size="xs"
className="font-bold"
disabled={emulation.state !== 'stop' && emulation.state !== 'pause'}
disabled={state !== 'stop' && state !== 'pause'}
onClick={emulation.run}
>
{t.run}
Expand All @@ -28,7 +29,7 @@ export const EditorEmulationToolbar = () => {
<Button
color="gray"
size="xs"
disabled={emulation.state !== 'running'}
disabled={state !== 'running'}
onClick={emulation.pause}
>
{t.pause}
Expand All @@ -41,7 +42,7 @@ export const EditorEmulationToolbar = () => {
<Button
color="failure"
size="xs"
disabled={emulation.state !== 'running' && emulation.state !== 'pause'}
disabled={state !== 'running' && state !== 'pause'}
onClick={emulation.stop}
>
{t.stop}
Expand Down
2 changes: 1 addition & 1 deletion apps/site/src/modules/Editor/Header/EditorLinksToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const EditorLinksToolbar = () => {
target="_blank"
rel="noreferrer noopener"
title={t.links.github}
className="text-gray-500"
className="text-gray-400"
>
<BiLogoGithub size={38} />
</a>
Expand Down
4 changes: 0 additions & 4 deletions apps/site/src/modules/Editor/Input/EditorInput.module.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
.editor-codemirror :global {
.CodeMirror {
height: 100%;

&-code {
padding-top: 16px;
}
}
}
1 change: 1 addition & 0 deletions apps/site/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './nullable.type';
1 change: 1 addition & 0 deletions apps/site/src/types/nullable.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Nullable<T> = T | null | undefined;
4 changes: 2 additions & 2 deletions packages/compiler-pico-c/src/backend/safeGenAsmIRCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as E from 'fp-ts/Either';
import { X86ArchBackend } from '../arch/x86';

import { CCompilerArch, CCompilerConfig } from '../constants';
import { IRResultView } from '../frontend/ir';
// import { IRResultView } from '../frontend/ir';

import { IRScopeGeneratorResult } from '../frontend/ir/generator';
import { CAbstractArchBackend } from './abstract/CAbstractArchBackend';
Expand All @@ -24,7 +24,7 @@ export function genASMIRCode(
try {
const CompilerBackend = CCOMPILER_ARCH_BACKENDS[config.arch];

console.info(IRResultView.serializeToString(ir));
// console.info(IRResultView.serializeToString(ir));

return E.right(new CompilerBackend(config).compileIR(ir));
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-pico-c/src/fs/std/stdio.h.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const STD_IO_CONTENT_HEADER = /* c */ `
}
}
int _printf(const char* str, ...) {
int printf(const char* str, ...) {
va_list ap;
va_start(ap, str);
Expand Down
4 changes: 4 additions & 0 deletions packages/x86-cpu/src/X86CPU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,10 @@ export class X86CPU extends X86AbstractCPU {
return num;
}

freeze() {
this.pause = true;
}

/**
* Shut down emulator, if dump is enabled show all registers into console
*/
Expand Down

0 comments on commit 999dff2

Please sign in to comment.