From 6418779a9d4fa4642dc2bec7d2252b452479c716 Mon Sep 17 00:00:00 2001 From: mistlog Date: Sat, 15 Aug 2020 21:56:21 +0800 Subject: [PATCH] implement inplace context --- package-lock.json | 8 +- package.json | 2 +- src/code-object/module.tsx | 18 ++-- src/core/transcriber.tsx | 12 ++- src/plug-in/draft-plugin-inplace-context.tsx | 43 ++++++++++ .../inplace-context.test.ts.snap | 23 +++++ test/plug-in/inplace-context.test.ts | 84 +++++++++++++++++++ 7 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 src/plug-in/draft-plugin-inplace-context.tsx create mode 100644 test/plug-in/__snapshots__/inplace-context.test.ts.snap create mode 100644 test/plug-in/inplace-context.test.ts diff --git a/package-lock.json b/package-lock.json index 945e193..b323965 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "typedraft", - "version": "0.2.2", + "version": "0.2.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -6748,9 +6748,9 @@ "dev": true }, "typedraft": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/typedraft/-/typedraft-0.2.2.tgz", - "integrity": "sha512-HI+Z8PlVfKvjCcMqpLeZxjvVtgJqFyIpBZ88oZ2tVvDtuWpB6k0MKtuSr+p0gwaXDjGcrL6a4D21FtFR48tlCw==", + "version": "0.0.0-31fb921", + "resolved": "https://registry.npmjs.org/typedraft/-/typedraft-0.0.0-31fb921.tgz", + "integrity": "sha512-1K5hOOkECMH2hxMhzqRas2g90oLMs7bcR07JtwTrZQtL7Ytdj2qhCtS/BaXueJ1ltti311YjXdOITU0eKctDXg==", "dev": true, "requires": { "@babel/core": "^7.6.2", diff --git a/package.json b/package.json index 27cb8bf..3e10872 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "pretty-quick": "^2.0.1", "ts-jest": "^24.0.2", "ts-node": "^8.3.0", - "typedraft": "0.2.2" + "typedraft": "0.0.0-31fb921" }, "husky": { "hooks": { diff --git a/src/code-object/module.tsx b/src/code-object/module.tsx index 1cc9634..47b9c19 100644 --- a/src/code-object/module.tsx +++ b/src/code-object/module.tsx @@ -13,7 +13,7 @@ export type Draft = Array + - function ToDraft(this: ModuleCode) { + function ToDraft(this: ModuleCode & IModuleCode) { /** * refresh and update bindings because DSL only transforms code */ @@ -23,8 +23,7 @@ export type Draft = Array( - this.m_File, + this.Traverse<{ _module: ModuleCode }>( { Program(path) { this._module.m_Path = path; @@ -43,7 +42,6 @@ export type Draft = Array(visitor: TraverseOptions, state: S): void; +} + + + + function Traverse(this: ModuleCode, visitor: TraverseOptions, state: S = null) { + this.m_File = ToFile(ToString(this.m_File)); + traverse(this.m_File, visitor, null, state); + }; + /** * ## Create draft */ @@ -136,5 +144,5 @@ import { ExportClassCode } from "./export-class"; import { MethodCode } from "./method"; import { LocalContext } from "./local-context"; import { ToFile, ToString } from "../common/utility"; -import traverse, { NodePath, Node } from "@babel/traverse"; +import traverse, { NodePath, Node, TraverseOptions } from "@babel/traverse"; import { InlineContext } from "./inline-context"; diff --git a/src/core/transcriber.tsx b/src/core/transcriber.tsx index e75ffc8..6a9462e 100644 --- a/src/core/transcriber.tsx +++ b/src/core/transcriber.tsx @@ -92,11 +92,13 @@ export class Transcriber { }; export interface IDSL { - Transcribe( + Transcribe?( block: Array, path?: NodePath | NodePath ): Array; + InplaceTranscribe?(literal: NodePath): Expression; + m_Merge?: boolean; } @@ -135,7 +137,13 @@ export type TraverseLocalContextCallback = (context: LocalContext, name: string) export type TraverseInlineContextCallback = (context: InlineContext) => void; export type TraverseMethodCallback = (methods: Array, class_name: string) => void; -import { Statement, FunctionDeclaration, BlockStatement } from "@babel/types"; +import { + Statement, + FunctionDeclaration, + BlockStatement, + Expression, + TemplateLiteral, +} from "@babel/types"; import { NodePath } from "@babel/traverse"; import { ToString } from "../common/utility"; diff --git a/src/plug-in/draft-plugin-inplace-context.tsx b/src/plug-in/draft-plugin-inplace-context.tsx new file mode 100644 index 0000000..3870cc1 --- /dev/null +++ b/src/plug-in/draft-plugin-inplace-context.tsx @@ -0,0 +1,43 @@ +import { ITranscriber } from "../core/transcriber"; +import { NodePath, Node } from "@babel/core"; +import { StringLiteral, Identifier } from "@babel/types"; + +export class InplaceContextPlugin { + m_Transcriber: ITranscriber; +} + + + + function constructor(this: InplaceContextPlugin, transcriber: ITranscriber) { + this.m_Transcriber = transcriber; + }; + + + + function Transcribe(this: InplaceContextPlugin) { + const transcriber = this.m_Transcriber; + transcriber.m_Module.Traverse({ + TaggedTemplateExpression(path) { + const tag = path.get("tag"); + if (!tag.isCallExpression()) { + return; + } + + const callee = tag.get("callee") as NodePath; + const callee_name = callee.node.name as string; + if (callee_name !== "context" && callee_name !== "Λ") { + return; + } + + const [arg] = (tag.get("arguments") as Array>) as [ + NodePath + ]; + const dsl_name = arg.node.value; + + const dsl = transcriber.m_DSLMap.get(dsl_name); + if (!dsl) { + return; + } + + path.replaceWith(dsl.InplaceTranscribe(path.get("quasi"))); + }, + }); + }; diff --git a/test/plug-in/__snapshots__/inplace-context.test.ts.snap b/test/plug-in/__snapshots__/inplace-context.test.ts.snap new file mode 100644 index 0000000..f885ca3 --- /dev/null +++ b/test/plug-in/__snapshots__/inplace-context.test.ts.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`not inplace context no dsl 1`] = ` +"const temp = Λ(\\"math\\")\` + 1+2 + \`;" +`; + +exports[`not inplace context not call expression 1`] = ` +"context\` + 1+2 + \`;" +`; + +exports[`not inplace context not context or Λ 1`] = ` +"whatever(\\"math\\")\` + 1+2 + \`;" +`; + +exports[`use inplace context as expression 1`] = `"const temp = \\"3\\";"`; + +exports[`use inplace context as expression statement 1`] = `"\\"3\\";"`; diff --git a/test/plug-in/inplace-context.test.ts b/test/plug-in/inplace-context.test.ts new file mode 100644 index 0000000..484331e --- /dev/null +++ b/test/plug-in/inplace-context.test.ts @@ -0,0 +1,84 @@ +import { MakeDefaultTranscriber, IDSL } from "../../src"; +import { InplaceContextPlugin } from "../../src/plug-in/draft-plugin-inplace-context"; +import { NodePath } from "@babel/core"; +import { TemplateLiteral, stringLiteral } from "@babel/types"; + +class Math implements IDSL { + InplaceTranscribe(literal: NodePath) { + return stringLiteral("3"); + } +} + +test("use inplace context as expression", () => { + // + const code = ` + const temp = Λ("math")\` + 1+2 + \`; + `; + + const transcriber = MakeDefaultTranscriber(code); + transcriber.m_Plugins = [new InplaceContextPlugin(transcriber)]; + transcriber.m_DSLMap.set("math", new Math()); + const result = transcriber.Transcribe(); + expect(result).toMatchSnapshot(); +}); + +test("use inplace context as expression statement", () => { + // + const code = ` + context("math")\` + 1+2 + \`; + `; + + const transcriber = MakeDefaultTranscriber(code); + transcriber.m_Plugins = [new InplaceContextPlugin(transcriber)]; + transcriber.m_DSLMap.set("math", new Math()); + const result = transcriber.Transcribe(); + expect(result).toMatchSnapshot(); +}); + +describe("not inplace context", () => { + test("not call expression", () => { + // + const code = ` + context\` + 1+2 + \`; + `; + + const transcriber = MakeDefaultTranscriber(code); + transcriber.m_Plugins = [new InplaceContextPlugin(transcriber)]; + const result = transcriber.Transcribe(); + expect(result).toMatchSnapshot(); + }); + + test("not context or Λ", () => { + // + const code = ` + whatever("math")\` + 1+2 + \`; + `; + + const transcriber = MakeDefaultTranscriber(code); + transcriber.m_Plugins = [new InplaceContextPlugin(transcriber)]; + const result = transcriber.Transcribe(); + expect(result).toMatchSnapshot(); + }); + + test("no dsl", () => { + // + const code = ` + const temp = Λ("math")\` + 1+2 + \`; + `; + + const transcriber = MakeDefaultTranscriber(code); + transcriber.m_Plugins = [new InplaceContextPlugin(transcriber)]; + const result = transcriber.Transcribe(); + expect(result).toMatchSnapshot(); + }); +});