Skip to content

Commit

Permalink
sad bug in the transpiler
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanThatOneKid committed Dec 21, 2021
1 parent f95dfeb commit 8680e26
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"https://cdn.skypack.dev": false,
"https://fart.tools": false
},
"cSpell.words": ["typemap", "typemaps"]
"cSpell.words": ["typedefs", "typemap", "typemaps"]
}
12 changes: 12 additions & 0 deletions lib/constants/lang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export enum Lang {
Fart = "fart", // ex use-case: generating typedefs/config in any lang
Proto = "proto", // ex use-case: generating typedefs in multiple langs
TypeScript = "ts", // ex use-case: generating all types of programs
ESM = "esm", // JavaScript with `import`
Go = "go", // ex use-case: generating all types of programs
Rust = "rust", // ex use-case: generating fault-tolerant programs
JSON = "json", // ex use-case: generating config
HTML = "html", // ex use-case: generating web pages
YAML = "yaml", // ex use-case: generating config
XML = "xml", // ex use-case: generating unstructured info
}
9 changes: 5 additions & 4 deletions lib/transpile/cartridge/cartridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,13 @@ export class Cartridge {
public async dispatch<T extends CartridgeEvent>(
name: CartridgeEvent,
ctx: CartridgeEventContext<T>,
): Promise<string | null | void> {
): Promise<string | null> {
const handleEvent = this.handlers[name] as CartridgeHandler<T>;
if (handleEvent === undefined) return null;
const executionResult = handleEvent(ctx);
return executionResult instanceof Promise
? await executionResult
: executionResult;
if (executionResult instanceof Promise) {
return await executionResult ?? null;
}
return executionResult ?? null;
}
}
6 changes: 4 additions & 2 deletions lib/transpile/text_builder/text_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CartridgeEvent,
PropertyDefinition,
} from "../cartridge/mod.ts";
import { Lexicon } from "../tokenize/mod.ts";
import type { Token } from "../tokenize/mod.ts";
import {
makeFileEndEventContext,
Expand All @@ -16,12 +17,12 @@ import {
makeStructCloseEventContext,
makeStructOpenEventContext,
} from "./utils.ts";
import { assertKind } from "../utils.ts";

export class TextBuilder {
private blocks: CodeBlock[];
private currentBlock: CodeBlock;
private indentLevel: number;

constructor(private cartridge: Cartridge) {
this.blocks = [];
this.currentBlock = new CodeBlock();
Expand Down Expand Up @@ -116,9 +117,10 @@ export class TextBuilder {
break;
}
case CartridgeEvent.StructOpen: {
const { value: name } = assertKind(tokens[1], Lexicon.Identifier);
code = await this.cartridge.dispatch(
CartridgeEvent.StructOpen,
makeStructOpenEventContext(this.currentBlock, tokens, comments),
makeStructOpenEventContext(this.currentBlock, tokens, comments, name),
);
break;
}
Expand Down
19 changes: 19 additions & 0 deletions lib/transpile/transpile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { assertEquals } from "../../deps/std/testing.ts";
import { transpile } from "./transpile.ts";
import { Cartridge, CartridgeEvent } from "./cartridge/mod.ts";
import type { CartridgeEventContext } from "./cartridge/mod.ts";
// import type { FartOptions } from "./transpile.ts";

Deno.test("empty string results in empty string", async () => {
const fakeCart = new Cartridge();
fakeCart.on(
CartridgeEvent.StructOpen,
(event: CartridgeEventContext<CartridgeEvent.StructOpen>) => {
assertEquals(event.data.name, "Example");
console.log({ event });
return "";
},
);
const result = await transpile(`type Example {`, fakeCart);
assertEquals(result, "");
});
71 changes: 45 additions & 26 deletions lib/transpile/transpile.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { Lexicon, Token, tokenize } from "./tokenize/mod.ts";
import { Cartridge, CartridgeEvent } from "./cartridge/mod.ts";
import { TextBuilder } from "./text_builder/mod.ts";
// import { Lang } from "../constants/lang.ts";
import { assertKind } from "./utils.ts";
import type { FartTokenGenerator } from "./tokenize/mod.ts";

/**
* @todo rethink these options since the codeCart determines the
* target language. The source language will be one of few supported
* langs: Fart and Proto.
*/
export interface FartOptions {
targetLanguage: string; // "ts" | "go"
sourceLanguage: string; // "fart" | "fart-pb" | "fart-go"
codeCartridges: Cartridge[];
codeCartridge: Cartridge; // TODO: allow for user to pass Cartridge[]
indentation: number;
preserveComments: boolean;
}

const assertKind = (token: Token | null, lexeme: Lexicon): Token => {
if (token === null || token.kind !== lexeme) {
throw new Error(`Expected token kind ${lexeme}, got ${token}`);
}
return token;
};

class TranspilationContext {
constructor(
public tokenizer?: FartTokenGenerator,
Expand Down Expand Up @@ -57,12 +57,28 @@ class TranspilationContext {
}
}

export const transpile = (
/**
* @todo impl options
* - targetLanguage: string; // "ts" | "go"
* - sourceLanguage: string; // "fart" | "fart-pb" | "fart-go"
* - codeCartridge: Cartridge; // TODO: allow for user to pass Cartridge[]
* - indentation: number;
* - preserveComments: boolean;
*/
export function transpile(
code: string,
// options: FartOptions,
): string => {
const builder = new TextBuilder(new Cartridge());
options: Cartridge | FartOptions,
): Promise<string> {
// const srcLang = (options as FartOptions).sourceLanguage ?? Lang.Fart;
// const targetLang = (options as FartOptions).sourceLanguage ?? Lang.TypeScript;
// const indentation: number | undefined = (options as FartOptions).indentation;
// const preserveComments = (options as FartOptions).preserveComments ?? false;
const cartridge = options instanceof Cartridge
? options
: options.codeCartridge;
const builder = new TextBuilder(cartridge);
const ctx = new TranspilationContext(tokenize(code), builder);

do {
switch (ctx.nextToken()?.kind) {
case Lexicon.Load: {
Expand All @@ -72,31 +88,34 @@ export const transpile = (
);
const source = assertKind(ctx.nextToken(), Lexicon.TextLiteral);
const opener = assertKind(ctx.nextToken(), Lexicon.StructOpener);
ctx.builder?.append(
CartridgeEvent.StructOpen,
[loader, source, opener],
[],
);
ctx.nextTuple();
console.log({ loader, source, opener });
// await ctx.builder?.append(
// CartridgeEvent.StructOpen,
// [loader, source, opener],
// [],
// );
// await ctx.nextTuple();
break;
}

case Lexicon.TypeDefiner: {
const definer = assertKind(
ctx.currentToken?.value as Token,
Lexicon.TypeDefiner,
);
const ident = assertKind(ctx.nextToken(), Lexicon.Identifier);
const opener = assertKind(ctx.nextToken(), Lexicon.StructOpener);
ctx.builder?.append(
CartridgeEvent.StructOpen,
[definer, ident, opener],
[],
);
ctx.nextStruct();
console.log({ definer, ident, opener });
// await ctx.builder?.append(
// CartridgeEvent.StructOpen,
// [definer, ident, opener],
// [],
// );
// await ctx.nextStruct();
break;
}
}
} while (!ctx.currentToken?.done);

return ctx.builder?.export() ?? "";
};
return Promise.resolve(ctx.builder?.export() ?? "");
}
13 changes: 13 additions & 0 deletions lib/transpile/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Lexicon, Token } from "./tokenize/mod.ts";

/**
* @todo write tests in utils.test.ts
*/
export function assertKind(token: Token | null, lexeme: Lexicon): Token {
if (token === null || token.kind !== lexeme) {
throw new Error(
`Expected token kind ${Lexicon[lexeme]}, got ${token}`,
);
}
return token;
}

1 comment on commit 8680e26

@deno-deploy
Copy link

@deno-deploy deno-deploy bot commented on 8680e26 Dec 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed to deploy:

failed to fetch 'https://raw.githubusercontent.com/EthanThatOneKid/fart/8680e26a2dfa8d04a4c825a2fde0583abe80369b/fart_server/handle_request.ts': HTTP status client error (404 Not Found) for url (https://raw.githubusercontent.com/EthanThatOneKid/fart/8680e26a2dfa8d04a4c825a2fde0583abe80369b/fart_server/handle_request.ts)

Please sign in to comment.