Skip to content

Commit

Permalink
Progress react pretty printer with lambdas
Browse files Browse the repository at this point in the history
  • Loading branch information
davazp committed Apr 2, 2020
1 parent 804a936 commit 2e27463
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 43 deletions.
23 changes: 2 additions & 21 deletions packages/delisp-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,7 @@ export { resolveModuleDependencies } from "./module-dependencies";
export { Encoder } from "./prettier";
export { default as primitives } from "./primitives";
export { pprint, pprintAs, pprintModule, pprintModuleAs } from "./printer";
export {
Declaration,
Expression,
isDeclaration,
isDefinition,
isExport,
isExpression,
isTypeAlias,
Identifier,
SNumber,
SString,
SBoolean,
SNone,
Module,
SDefinition,
SExport,
STypeAlias,
SRecord,
Syntax,
} from "./syntax";
export * from "./syntax";
export { Typed } from "./syntax-typed";
export {
exprFChildren,
Expand All @@ -70,7 +51,7 @@ export {
createVariableNormalizer,
TypeVariableNormalizer,
} from "./type-printer";
export { isFunctionType, decomposeFunctionType } from "./type-utils";
export * from "./type-utils";
export { Type } from "./types";
export { generateTSModuleDeclaration } from "./typescript-generation";
export {
Expand Down
18 changes: 16 additions & 2 deletions packages/liphe/pages/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@
}

.record ul {
list-style-type: none;
padding-left: 20px;
list-style-type: none;
padding-left: 20px;
}

.identifier {
color: blue;
}

.function {
border: 1px solid lightGray;
padding: 5px;
}

.functionLabel {
font-size: 2em;
font-weight: bold;
}

.functionArguments .identifier {
color: purple;
}
137 changes: 118 additions & 19 deletions packages/liphe/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,73 @@
import * as React from "react";
import { useState, useContext } from "react";
import * as Delisp from "@delisp/core";
import { Typed } from "@delisp/core";
import { PageLayout } from "../components/PageLayout";

import { GenericSyntaxExplorer } from "./pprinter";

import styles from "./index.module.css";

export const ModuleExplorer: React.FC<{ module: Delisp.Module }> = ({
const Context = React.createContext<
ReturnType<typeof Delisp.createVariableNormalizer>
>(null as any);

export const ModuleExplorer: React.FC<{ module: Delisp.Module<Typed> }> = ({
module,
}) => {
return (
<div className={styles.module}>
{module.body.map((syntax, i) => (
<SyntaxExplorer key={i} syntax={syntax} />
<ToplevelSyntaxExplorer key={i} syntax={syntax} />
))}
</div>
);
};

export const SyntaxExplorer: React.FC<{ syntax: Delisp.Syntax }> = ({
export const ToplevelSyntaxExplorer: React.FC<{
syntax: Delisp.Syntax<Typed>;
}> = ({ syntax }) => {
const [raw, setRaw] = useState(false);
const normalizer = Delisp.createVariableNormalizer();

const content = (() => {
if (raw) {
return <GenericSyntaxExplorer syntax={syntax} normalizer={normalizer} />;
} else {
return <SyntaxExplorer syntax={syntax} />;
}
})();

return (
<Context.Provider value={normalizer}>
<div>
<button
onClick={() => {
setRaw(!raw);
}}
>
{raw ? "Rich" : "Text"}
</button>
{content}
</div>
</Context.Provider>
);
};

export const SyntaxExplorer: React.FC<{ syntax: Delisp.Syntax<Typed> }> = ({
syntax,
}) => {
if (Delisp.isExpression(syntax)) {
return <ExpressionExplorer expression={syntax} />;
} else {
return null;
}
const normalizer = useContext(Context);
const content = Delisp.isExpression(syntax) ? (
<ExpressionExplorer expression={syntax} />
) : (
<GenericSyntaxExplorer syntax={syntax} normalizer={normalizer} />
);
return <div>{content}</div>;
};

export const ExpressionExplorer: React.FC<{
expression: Delisp.Expression;
expression: Delisp.Expression<Typed>;
}> = ({ expression }) => {
switch (expression.node.tag) {
case "number":
Expand All @@ -44,13 +84,18 @@ export const ExpressionExplorer: React.FC<{
return (
<BooleanExplorer value={{ ...expression, node: expression.node }} />
);

case "function":
return <FunctionExplorer fn={{ ...expression, node: expression.node }} />;
case "record":
return (
<RecordExplorer record={{ ...expression, node: expression.node }} />
);
default:
return null;
default: {
const normalizer = useContext(Context);
return (
<GenericSyntaxExplorer syntax={expression} normalizer={normalizer} />
);
}
}
};

Expand Down Expand Up @@ -80,7 +125,7 @@ export const NoneExplorer: React.FC<{ value: Delisp.SNone }> = () => {
};

export const RecordExplorer: React.FC<{
record: Delisp.SRecord;
record: Delisp.SRecord<Typed>;
}> = ({ record }) => {
return (
<div className={styles.record}>
Expand All @@ -90,7 +135,7 @@ export const RecordExplorer: React.FC<{
return (
<li key={field.label.name}>
<IdentifierExplorer identifier={field.label} />{" "}
<ExpressionExplorer expression={field.value} />
<SyntaxExplorer syntax={field.value} />
</li>
);
})}
Expand All @@ -100,6 +145,56 @@ export const RecordExplorer: React.FC<{
);
};

export const FunctionExplorer: React.FC<{ fn: Delisp.SFunction<Typed> }> = ({
fn,
}) => {
const selfType = fn.info.selfType;
if (!Delisp.isFunctionType(selfType)) {
throw new Error("The type of a function is not a function type??");
}
const type = Delisp.decomposeFunctionType(selfType);

return (
<div className={styles.function}>
<span className={styles.functionLabel}>λ</span>

<ul className={styles.functionArguments}>
{fn.node.lambdaList.positionalArguments.map((arg, argPosition) => {
return (
<li key={arg.name}>
<IdentifierExplorer identifier={arg} /> -
<TypeExplorer type={type.args[argPosition]} />
</li>
);
})}
</ul>

<div>
<strong>Effect:</strong>
<TypeExplorer type={type.effect} />
</div>

<div>
<strong>Output:</strong>
<TypeExplorer type={type.output} />
</div>

{fn.node.body.map((expr, i) => {
return <SyntaxExplorer key={i} syntax={expr} />;
})}
</div>
);
};

export const TypeExplorer: React.FC<{ type: Delisp.Type }> = ({ type }) => {
const normalizer = useContext(Context);
return (
<span className="type">
{Delisp.printTypeWithNormalizer(type, normalizer)}
</span>
);
};

export const IdentifierExplorer: React.FC<{
identifier: Delisp.Identifier;
}> = ({ identifier }) => {
Expand All @@ -111,14 +206,18 @@ export const IdentifierExplorer: React.FC<{
};

export default function Homepage() {
const module = Delisp.readModule(`
{:x 10 :y 20 :z {:name "david"}}
`);
const module = Delisp.macroexpandModule(
Delisp.readModule(`
(lambda (x1 x2) {:x (+ x1 x2) :y 20 :z {:name "david"} :callback (lambda () 3)})
`)
);

const { typedModule } = Delisp.inferModule(module);

return (
<div>
<PageLayout>
<div>test</div>
<ModuleExplorer module={module} />
<ModuleExplorer module={typedModule} />
</PageLayout>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/liphe/pages/pprinter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ function createPrettierEncoder(
};
}

function GenericSyntaxExplorer({
export function GenericSyntaxExplorer({
syntax,
normalizer,
}: {
Expand Down

0 comments on commit 2e27463

Please sign in to comment.