Skip to content

Commit

Permalink
implement inline context
Browse files Browse the repository at this point in the history
  • Loading branch information
mistlog committed Jun 7, 2020
1 parent e9a750f commit 4362955
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 16 deletions.
4 changes: 4 additions & 0 deletions docs/toc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"page": "Local Context",
"file": "src/code-object/local-context.html"
},
{
"page": "Inline Context",
"file": "src/code-object/inline-context.html"
},
{
"page": "Module and Draft",
"file": "src/code-object/module.html"
Expand Down
45 changes: 45 additions & 0 deletions src/code-object/inline-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
export class InlineContext {
m_Path: NodePath<BlockStatement>;

get m_ID() {
return Symbol();
}

get m_Code() {
return this.m_Path.node as BlockStatement;
}
}

<InlineContext /> +
function constructor(this: InlineContext, path: NodePath<BlockStatement>) {
this.m_Path = path;
};

<InlineContext /> +
function ToStatements(this: InlineContext) {
return this.m_Code.body;
};

<InlineContext /> +
function Resolve(this: InlineContext & IInlineContext, dsl: IDSL) {
this.m_Code.body = dsl.Transcribe(this.ToStatements(), this.m_Path);
};

<InlineContext /> +
function GetContextName(this: InlineContext) {
const statement = this.m_Path.node.body[0] as ExpressionStatement;
if (!statement) {
return "";
}

const [, dsl_name] = (statement.expression as StringLiteral).value.trim().split(" ");
return dsl_name;
};

export interface IInlineContext {
ToStatements: () => Array<Statement>;
}

import { BlockStatement, StringLiteral, ExpressionStatement, Statement } from "@babel/types";
import { NodePath } from "@babel/traverse";
import { IDSL } from "../core/transcriber";
17 changes: 14 additions & 3 deletions src/code-object/module.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* # Draft
* A .tsx file is considered as a module and we will transform these 3 types of code, they are collected and then transcibed to "real" code.
* A .tsx file is considered as a module and we will transform these 4 types of code, they are collected and then transcibed to "real" code.
*/
export class ModuleCode {
m_File: File;
m_Path: NodePath<Program>;
}

export type Draft = Array<ExportClassCode | MethodCode | LocalContext>;
export type Draft = Array<ExportClassCode | MethodCode | LocalContext | InlineContext>;

/**
* As we are only interested in the draft part of a module, then we need a way to return this "view" of module code.
Expand All @@ -22,12 +22,23 @@ export type Draft = Array<ExportClassCode | MethodCode | LocalContext>;
/**
* traverse file and set path
*/
let draft: Draft = [];
traverse<{ _module: ModuleCode }>(
this.m_File,
{
Program(path) {
this._module.m_Path = path;
},

ExpressionStatement(path) {
const expression = path.get("expression");
if (expression.isStringLiteral()) {
const literal = expression.node.value.trim();
if (literal.startsWith("use") && path.parentPath.isBlockStatement()) {
draft.push(new InlineContext(path.parentPath));
}
}
},
},
null,
{ _module: this }
Expand All @@ -36,7 +47,6 @@ export type Draft = Array<ExportClassCode | MethodCode | LocalContext>;
/**
* collect draft parts
*/
let draft: Draft = [];
this.m_Path.get("body").forEach(path => {
//@ts-ignore
<AddToDraft />;
Expand Down Expand Up @@ -124,3 +134,4 @@ import { MethodCode } from "./method";
import { LocalContext } from "./local-context";
import { ToFile, ToString } from "../common/utility";
import traverse, { NodePath, Node } from "@babel/traverse";
import { InlineContext } from "./inline-context";
22 changes: 18 additions & 4 deletions src/core/transcriber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ export class Transcriber {
m_Module: ModuleCode;

/**
* the 3 types of code we will transform
* the 4 types of code we will transform
*/
m_ClassMap: Map<string, ExportClassCode>;
m_MethodMap: Map<string, Array<MethodCode>>;
m_ContextMap: Map<string, LocalContext>;
m_InlineContextMap: Map<Symbol, InlineContext>;

m_DSLMap: Map<string, IDSL>;
m_Plugins: Array<IPlugin>;
Expand Down Expand Up @@ -54,7 +55,7 @@ export class Transcriber {
<Transcriber /> + function PrepareDSLs(this: Transcriber) {};

/**
* ## Local Context and Class
* ## Context and Class
*/
<Transcriber /> +
function GetLocalContext(this: Transcriber, name: string) {
Expand All @@ -66,6 +67,11 @@ export class Transcriber {
this.m_ContextMap.forEach((context, name) => callback(context, name));
};

<Transcriber /> +
function TraverseInlineContext(this: Transcriber, callback: TraverseInlineContextCallback) {
this.m_InlineContextMap.forEach(context => callback(context));
};

<Transcriber /> +
function GetClass(this: Transcriber, name: string) {
return this.m_ClassMap.get(name);
Expand All @@ -86,14 +92,18 @@ export class Transcriber {
this.m_ClassMap = new Map<string, ExportClassCode>();
this.m_MethodMap = new Map<string, Array<MethodCode>>();
this.m_ContextMap = new Map<string, LocalContext>();
this.m_InlineContextMap = new Map<Symbol, InlineContext>();
this.m_DSLMap = new Map<string, IDSL>();

this.PrepareDSLs();
this.PreparePlugins();
};

export interface IDSL {
Transcribe(block: Array<Statement>, path?: NodePath<FunctionDeclaration>): Array<Statement>;
Transcribe(
block: Array<Statement>,
path?: NodePath<FunctionDeclaration> | NodePath<BlockStatement>
): Array<Statement>;
}

export interface IPlugin {
Expand All @@ -110,6 +120,7 @@ export interface ITranscriber {

TraverseMethod: (callback: TraverseMethodCallback) => void;
TraverseLocalContext: (callback: TraverseLocalContextCallback) => void;
TraverseInlineContext: (callback: TraverseInlineContextCallback) => void;

m_Module: ModuleCode;

Expand All @@ -119,14 +130,16 @@ export interface ITranscriber {
m_ClassMap: Map<string, ExportClassCode>;
m_MethodMap: Map<string, Array<MethodCode>>;
m_ContextMap: Map<string, LocalContext>;
m_InlineContextMap: Map<Symbol, InlineContext>;

m_DSLMap: Map<string, IDSL>;
}

export type TraverseLocalContextCallback = (context: LocalContext, name: string) => void;
export type TraverseInlineContextCallback = (context: InlineContext) => void;
export type TraverseMethodCallback = (methods: Array<MethodCode>, class_name: string) => void;

import { Statement, FunctionDeclaration } from "@babel/types";
import { Statement, FunctionDeclaration, BlockStatement } from "@babel/types";
import { NodePath } from "@babel/traverse";

import { ToString } from "../common/utility";
Expand All @@ -135,3 +148,4 @@ import { ModuleCode } from "../code-object/module";
import { ExportClassCode } from "../code-object/export-class";
import { MethodCode } from "../code-object/method";
import { LocalContext } from "../code-object/local-context";
import { InlineContext } from "../code-object/inline-context";
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from "./core/transcriber";

export * from "./code-object/export-class";
export * from "./code-object/local-context";
export * from "./code-object/inline-context";
export * from "./code-object/method";
export * from "./code-object/module";

Expand Down
8 changes: 8 additions & 0 deletions src/plug-in/draft-plugin-dsl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ export class DSLPlugin {

<DSLPlugin /> +
function Transcribe(this: DSLPlugin) {
this.m_Transcriber.TraverseInlineContext(context => {
const context_name = context.GetContextName();
const dsl = this.m_Transcriber.GetDSL(context_name);
if (dsl) {
context.Resolve(dsl);
}
});

this.m_Transcriber.TraverseLocalContext(context => {
const context_name = context.GetContextName();
const dsl = this.m_Transcriber.GetDSL(context_name);
Expand Down
4 changes: 4 additions & 0 deletions src/plug-in/draft-plugin-refresh.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IPlugin, ITranscriber } from "../core/transcriber";
import { ExportClassCode } from "../code-object/export-class";
import { MethodCode } from "../code-object/method";
import { LocalContext } from "../code-object/local-context";
import { InlineContext } from "../code-object/inline-context";

export class RefreshDraftPlugin implements IPlugin {
m_Transcriber: ITranscriber;
Expand All @@ -17,6 +18,7 @@ export class RefreshDraftPlugin implements IPlugin {
this.m_Transcriber.m_ClassMap.clear();
this.m_Transcriber.m_MethodMap.clear();
this.m_Transcriber.m_ContextMap.clear();
this.m_Transcriber.m_InlineContextMap.clear();

/**
* prepare draft
Expand All @@ -33,6 +35,8 @@ export class RefreshDraftPlugin implements IPlugin {
: this.m_Transcriber.m_MethodMap.set(class_name, [each]);
} else if (each instanceof LocalContext) {
this.m_Transcriber.m_ContextMap.set(each.m_Name, each);
} else if (each instanceof InlineContext) {
this.m_Transcriber.m_InlineContextMap.set(each.m_ID, each);
}
});
}
Expand Down
33 changes: 33 additions & 0 deletions test/code-object/inline-context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ToNodePath, ToAst, InlineContext } from "../../src";
import { Statement } from "@babel/types";

test("get context name", () => {
const context = new InlineContext(
ToNodePath(`
{
'use foo';
console.log("previous");
}
`)
);
expect(context.GetContextName()).toEqual("foo");
});

test("to statement", () => {
//
const context = new InlineContext(
ToNodePath(`
{
'use foo';
console.log("previous");
}
`)
);

//
const expected = ToAst<Array<Statement>>(`
'use foo';
console.log("previous");
`);
expect(context.ToStatements()).toEqual(expected);
});
10 changes: 10 additions & 0 deletions test/plug-in/__snapshots__/dsl.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`inline context 1`] = `
"export function Main() {
console.log(\\"hello\\");
{
console.log(\\"current\\");
}
console.log(\\"world\\");
}"
`;

exports[`local context added after dsl resolved 1`] = `
"export function Main() {
if (value === \\"a\\") {
Expand Down
35 changes: 26 additions & 9 deletions test/plug-in/dsl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@ import {
import { NodePath } from "@babel/traverse";
import { PatternMatch } from "draft-dsl-match";

test("simple", () => {
//
class Foo implements IDSL {
Transcribe(block: Array<Statement>): Array<Statement> {
const transcribed = ToAst(`
console.log("current");
`);
class Foo implements IDSL {
Transcribe(block: Array<Statement>): Array<Statement> {
const transcribed = ToAst(`
console.log("current");
`);

return [transcribed as Statement];
}
return [transcribed as Statement];
}
}

test("simple", () => {
//
const code = `
export function Main(){
Expand Down Expand Up @@ -138,3 +137,21 @@ test("use path param", () => {
const result = transcriber.Transcribe();
expect(result).toMatchSnapshot();
});

test("inline context", () => {
const code = `
export function Main(){
console.log("hello");
{
'use foo';
console.log("previous");
}
console.log("world");
}
`;

const transcriber = MakeDefaultTranscriber(code);
transcriber.AddDSL("foo", new Foo());
const result = transcriber.Transcribe();
expect(result).toMatchSnapshot();
});

0 comments on commit 4362955

Please sign in to comment.