From 46baad7cf483e791dbe604f6e4928a28d2c005c9 Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Sat, 17 May 2025 18:01:31 +0200 Subject: [PATCH] self-host fonts; proper error bubbling --- package.json | 2 ++ pnpm-lock.yaml | 16 ++++++++++++++++ src/Editor.css | 17 ++++++++--------- src/Editor.tsx | 2 +- src/InputBlock.css | 15 +++------------ src/eval.ts | 37 ++++++++++++++++++++++++++++--------- src/index.css | 5 ++--- src/main.tsx | 3 +++ 8 files changed, 63 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index c653cb2..ca9751f 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "@fontsource-variable/inconsolata": "^5.2.5", + "@fontsource-variable/roboto": "^5.2.5", "dope2": "git+https://deemz.org/git/joeri/dope2.git", "react": "^19.1.0", "react-dom": "^19.1.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4fe0828..636f8b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,12 @@ importers: .: dependencies: + '@fontsource-variable/inconsolata': + specifier: ^5.2.5 + version: 5.2.5 + '@fontsource-variable/roboto': + specifier: ^5.2.5 + version: 5.2.5 dope2: specifier: git+https://deemz.org/git/joeri/dope2.git version: git+https://deemz.org/git/joeri/dope2.git#0096bb5559224b4c9bbe74317e07dc71cfc09c70 @@ -242,6 +248,12 @@ packages: resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fontsource-variable/inconsolata@5.2.5': + resolution: {integrity: sha512-CqYyjFNuArFv+cLRQodR+A9jJm2UMnBoP29yjYqjkd7Cgwz3pnMs3p68kmUb6VD/UqpDQR3deYTwa7RWFPOFew==} + + '@fontsource-variable/roboto@5.2.5': + resolution: {integrity: sha512-csqBSOWXv0h5IbPhEqYJua6/nxl7dSNZbBOMeXSO9aqzgPw3GpfgC9kL5M6ULFLRaoDoBD4U9QctoDLKMaTyMg==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1403,6 +1415,10 @@ snapshots: '@eslint/core': 0.13.0 levn: 0.4.1 + '@fontsource-variable/inconsolata@5.2.5': {} + + '@fontsource-variable/roboto@5.2.5': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': diff --git a/src/Editor.css b/src/Editor.css index 5253c6f..4b0b07a 100644 --- a/src/Editor.css +++ b/src/Editor.css @@ -1,14 +1,18 @@ .editor { + padding: 2px;; +} +.editor.error { + border: 1px solid red; + display: inline-block; +} +.offending .error { + background-color: transparent; } .typeSignature { display: inline-block; - /* display: none; */ - /* position: absolute; */ z-index: 1; - /* background-color: white; */ - /* border: 1px solid black; */ } .editor:hover > .typeSignature { @@ -23,9 +27,4 @@ .keyword { color: blue; font-weight: bold; - /* vertical-align: top; */ -} - -* { - /* vertical-align: top; */ } diff --git a/src/Editor.tsx b/src/Editor.tsx index 9abc86b..49c6eee 100644 --- a/src/Editor.tsx +++ b/src/Editor.tsx @@ -192,7 +192,7 @@ export function Editor({state, setState, onCancel, suggestionPriority}: EditorPr } } const resolved = evalEditorBlock(state, env); - return + return {renderBlock()}
 ::  diff --git a/src/InputBlock.css b/src/InputBlock.css index 57a52aa..99a7b9a 100644 --- a/src/InputBlock.css +++ b/src/InputBlock.css @@ -1,26 +1,17 @@ -@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@500&display=swap'); - .inputBlock { position: relative; } .editable { position: relative; - outline: 0px solid transparent; - display: inline-block; border: 0; - font-size: 13pt; - font-family: "Inconsolata", monospace; - font-optical-sizing: auto; - font-weight: 500; - font-style: normal; - font-variation-settings: "wdth" 100; + font-size: 10pt; + font-family: var(--my-monospace-font); background-color: transparent; color: inherit; padding: 0; } .suggest { - left: 0; - top: 0; + top: 2.4px; position: absolute; color: #aaa; } diff --git a/src/eval.ts b/src/eval.ts index a4f2af3..8ced53f 100644 --- a/src/eval.ts +++ b/src/eval.ts @@ -1,4 +1,4 @@ -import { assignFnSubstitutions, dict, Double, fnType, getSymbol, growEnv, Int, makeGeneric, NotAFunctionError, prettyT, set, substitute, symbolFunction, trie, TYPE_VARS, UnifyError } from "dope2"; +import { assignFnSubstitutions, dict, Double, fnType, getSymbol, growEnv, Int, NotAFunctionError, prettyT, substitute, symbolFunction, trie, TYPE_VARS, UnifyError } from "dope2"; import type { EditorState } from "./Editor"; import type { InputValueType, SuggestionType } from "./InputBlock"; @@ -68,13 +68,16 @@ export function evalInputBlock(text: string, value: InputValueType, env): Resolv ...found, substitutions: new Map(), }; - } else { - return entirelyUnknown(env); } } - else { // kind === "text" -> unresolved - return entirelyUnknown(env); - } + // kind === "text" -> unresolved + return { + kind: "error", + t: getUnusedTypeVar(env), + e: new Error(`'${text}' not found`), + depth: 0, + substitutions: new Map(), + }; } const mergeMaps = (...maps: Map[]) => { @@ -166,7 +169,8 @@ export function evalCallBlock(fn: EditorState, input: EditorState, env): Resolve export function evalLetInBlock(value: EditorState, name: string, inner: EditorState, env): ResolvedType { const valueResolved = evalEditorBlock(value, env); - const innerEnv = makeInnerEnv(env, name, valueResolved) + // console.log('eval', name, '...', valueResolved.kind, valueResolved.e); + const innerEnv = makeInnerEnv(env, name, valueResolved); return evalEditorBlock(inner, innerEnv); } @@ -181,14 +185,29 @@ export function getUnusedTypeVar(env) { export function evalLambdaBlock(paramName: string, expr: EditorState, env): ResolvedType { const paramType = getUnusedTypeVar(env); // static env: we only know the name and the type - const staticInnerEnv = makeInnerEnv(env, paramName, { + const staticInnerEnv = growEnv(env)(paramName)({ kind: "unknown", // parameter value is not statically known t: paramType, substitutions: new Map(), - }); + }) + // const staticInnerEnv = makeInnerEnv(env, paramName, { + // kind: "unknown", // parameter value is not statically known + // t: paramType, + // substitutions: new Map(), + // }); const exprResolved = evalEditorBlock(expr, staticInnerEnv); const lambdaT = fnType(_ => paramType)(_ => exprResolved.t); const lambdaTSubstituted = substitute(lambdaT, exprResolved.substitutions, []); + // console.log('inner kind', exprResolved.kind, paramName); + if (exprResolved.kind === "error") { + return { + kind: "error", + t: lambdaTSubstituted, + depth: 0, + e: exprResolved.e, + substitutions: staticInnerEnv.substitutions, + } + } const paramTypeSubstituted = lambdaTSubstituted.params[0](lambdaTSubstituted); const fn = (x: any) => { const innerEnv = makeInnerEnv(env, paramName, { diff --git a/src/index.css b/src/index.css index 79c747d..5d7afd2 100644 --- a/src/index.css +++ b/src/index.css @@ -1,6 +1,3 @@ -@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); - - body { margin: 0; font-family: "Roboto", sans-serif; @@ -8,6 +5,8 @@ body { font-weight: 400; font-style: normal; font-variation-settings: "wdth" 100; + --my-monospace-font: 'Inconsolata', monospace; + cursor: default; } kbd { diff --git a/src/main.tsx b/src/main.tsx index ee85237..dffec85 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -3,6 +3,9 @@ import { createRoot } from 'react-dom/client' import { App } from './App.tsx' import './index.css' +import '@fontsource-variable/inconsolata/standard.css'; +import '@fontsource-variable/roboto/standard.css'; + createRoot(document.getElementById('root')!).render(