Skip to content

Commit

Permalink
Merge pull request #303 from betwixt-labs/ts-ext
Browse files Browse the repository at this point in the history
feat: types for CompilerContext
  • Loading branch information
andrewmd5 authored Mar 11, 2024
2 parents 8dbb630 + 2a1feff commit aea4815
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 6 deletions.
4 changes: 4 additions & 0 deletions Core/Generators/GeneratorContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ private static void WriteArray(ArrayType arrayType, Utf8JsonWriter writer)
writer.WriteStartObject("array");
writer.WriteNumber("depth", depth);
writer.WriteString("memberType", memberType.ToTokenString());
if (memberType is MapType mt)
{
WriteMap(mt, writer);
}
writer.WriteEndObject();
}

Expand Down
4 changes: 4 additions & 0 deletions Core/IO/BinarySchemaWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ private void WriteArray(ArrayType arrayType)
}
_writer.Write(depth);
_writer.Write(TypeToId(memberType));
if (memberType is MapType mt)
{
WriteMap(mt);
}
}

private void WriteMap(MapType mapType)
Expand Down
82 changes: 77 additions & 5 deletions extensions/edks/typescript/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,82 @@
import { IndentedStringBuilder, commitResult, readContext } from "./kernel";
import { CompilerContext, IndentedStringBuilder, commitResult, readContext } from "./kernel";

export function chordCompile() {
const input = readContext();

commitResult(generateDocumentation(input));
}

function generateDocumentation(context: CompilerContext): string {
const builder = new IndentedStringBuilder();
builder.codeBlock("pseudo", 2, () => {
builder.appendLine("hello world");
});
commitResult(`${input} \n ${builder.toString()}`);

builder.appendLine(`Compiler Context Documentation`);
builder.appendLine(`===============================`);
builder.appendLine();

// Generate constants table
builder.appendLine(`Constants:`);
builder.appendLine(`+--------+--------+-------+`);
builder.appendLine(`| Name | Type | Value |`);
builder.appendLine(`+--------+--------+-------+`);
for (const [name, constant] of Object.entries(context.constants)) {
builder.appendLine(`| ${pad(name, 6)} | ${pad(constant.type, 6)} | ${pad(constant.value, 5)} |`);
}
builder.appendLine(`+--------+--------+-------+`);
builder.appendLine();

// Generate definitions table
builder.appendLine(`Definitions:`);
builder.appendLine(`+-------------+----------+`);
builder.appendLine(`| Name | Kind |`);
builder.appendLine(`+-------------+----------+`);
for (const [name, definition] of Object.entries(context.definitions)) {
builder.appendLine(`| ${pad(name, 11)} | ${pad(definition.kind, 8)} |`);
}
builder.appendLine(`+-------------+----------+`);
builder.appendLine();

// Generate fields table for each struct definition
for (const [name, definition] of Object.entries(context.definitions)) {
if (definition.kind === "struct") {
builder.appendLine(`Fields for struct "${name}":`);
builder.appendLine(`+-------------+----------+`);
builder.appendLine(`| Name | Type |`);
builder.appendLine(`+-------------+----------+`);
for (const [fieldName, field] of Object.entries(definition.fields)) {
builder.appendLine(`| ${pad(fieldName, 11)} | ${pad(field.type, 8)} |`);
}
builder.appendLine(`+-------------+----------+`);
builder.appendLine();
}
}

// Generate services table
builder.appendLine(`Services:`);
builder.appendLine(`+-------------+`);
builder.appendLine(`| Name |`);
builder.appendLine(`+-------------+`);
for (const [name, service] of Object.entries(context.services)) {
builder.appendLine(`| ${pad(name, 11)} |`);
}
builder.appendLine(`+-------------+`);
builder.appendLine();

// Generate methods table for each service
for (const [serviceName, service] of Object.entries(context.services)) {
builder.appendLine(`Methods for service "${serviceName}":`);
builder.appendLine(`+----------------+-------------+-------------+`);
builder.appendLine(`| Name | Request | Response |`);
builder.appendLine(`+----------------+-------------+-------------+`);
for (const [methodName, method] of Object.entries(service.methods)) {
builder.appendLine(`| ${pad(methodName, 14)} | ${pad(method.requestType, 11)} | ${pad(method.responseType, 11)} |`);
}
builder.appendLine(`+----------------+-------------+-------------+`);
builder.appendLine();
}

return builder.toString();
}

function pad(str: string, length: number): string {
return str.padEnd(length, " ");
}
129 changes: 128 additions & 1 deletion extensions/edks/typescript/src/kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function writeFileSync(fd: number, buffer: Uint8Array) {

export const readContext = () => {
const input = decoder.decode(readFileSync(STDIO.StdIn));
return JSON.parse(input);
return JSON.parse(input) as CompilerContext;
};

export const commitResult = (result: string) => {
Expand Down Expand Up @@ -176,3 +176,130 @@ export class IndentedStringBuilder {
return this.builder.join("");
}
}


export type BaseType = "uint8" | "uint16" | "uint32" | "uint64" | "int8" | "int16" | "int32" | "int64" | "float32" | "float64" | "bool" | "string" | "guid" | "date";

export type Kind = "enum" | "struct" | "message" | "union" | "service" | "const";


export type Decorator = {
[key: string]: {
arguments?: {
[key: string]: {
type: BaseType;
value: string;
};
};
};
};

export type ArrayType = {
depth: number;
memberType: BaseType | "map";
map?: MapType;
};

export type MapType = {
keyType: BaseType;
valueType: BaseType | "map" | "array";
array?: ArrayType;
map?: MapType;
};

export type Field<T extends BaseType | "array" | "map"> = {
documentation?: string;
decorators?: Decorator;
type: T;
index?: number;
array?: T extends "array" ? ArrayType : never;
map?: T extends "map" ? MapType : never;
};

export type EnumMember = {
documentation?: string;
decorators?: Decorator;
value: string;
};

export type BaseDefinition<K extends Kind> = {
kind: K;
documentation?: string;
decorators?: Decorator;
minimalEncodedSize: number;
discriminatorInParent?: number;
parent?: string;
};

export type EnumDefinition = BaseDefinition<"enum"> & {
isBitFlags?: boolean;
baseType?: BaseType;
members: {
[key: string]: EnumMember;
};
};

export type StructDefinition = BaseDefinition<"struct"> & {
mutable: boolean;
isFixedSize: boolean;
fields: {
[key: string]: Field<BaseType | "array" | "map">;
};
};

export type MessageDefinition = BaseDefinition<"message"> & {
fields: {
[key: string]: Field<BaseType | "array" | "map">;
};
};

export type UnionDefinition = BaseDefinition<"union"> & {
branches: {
[key: string]: number;
};
};

export type Method = {
decorators?: Decorator;
documentation?: string;
type: "Unary" | "DuplexStream" | "ClientStream" | "ServerStream";
requestType: string;
responseType: string;
id: number;
};

export type ServiceDefinition = BaseDefinition<"service"> & {
methods: {
[key: string]: Method;
};
};

export type ConstDefinition = BaseDefinition<"const"> & {
type: BaseType;
value: string;
};

export type Config = {
alias: string;
outFile: string;
namespace: string;
emitNotice: boolean;
emitBinarySchema: boolean;
services: "both" | "server" | "client";
options: {
[key: string]: string;
};
};

export type CompilerContext = {
definitions: {
[key: string]: EnumDefinition | StructDefinition | MessageDefinition | UnionDefinition;
};
services: {
[key: string]: ServiceDefinition;
};
constants: {
[key: string]: ConstDefinition;
};
config: Config;
};

0 comments on commit aea4815

Please sign in to comment.