@kipper/target-js
Version:
The JavaScript target for the Kipper compiler 🦊
149 lines (123 loc) • 5.63 kB
text/typescript
/**
* The TypeScript target-specific built-ins generator for generating the code that allows for the use of built-in
* functions.
* @since 0.10.0
*/
import type {
BuiltInFunction,
BuiltInVariable,
InternalFunction,
KipperProgramContext,
TranslatedCodeLine,
} from "@kipper/core";
import { KipperTargetBuiltInGenerator } from "@kipper/core";
import { createJSFunctionSignature, getJSFunctionSignature } from "./tools";
import { TargetJS } from "./target";
/**
* Generates a JavaScript function from the given signature and body.
* @param signature The signature of the function.
* @param body The body of the function.
* @param ignoreParams Whether or not to ignore the parameters of the function.
* @since 0.10.0
*/
export function genJSFunction(
signature: { identifier: string; params: string[] },
body: string,
ignoreParams: boolean = false,
): Array<TranslatedCodeLine> {
return [[signature.identifier, ":", " ", createJSFunctionSignature(signature, ignoreParams), " ", body]];
}
/**
* Generates a JavaScript local or global variable from the given variable and value.
* @param varSpec The variable to generate.
* @param value The value of the variable.
*/
export function genJSVariable(varSpec: BuiltInVariable, value: string): TranslatedCodeLine {
if (varSpec.local) {
return ["const", " ", TargetJS.getBuiltInIdentifier(varSpec), " ", "=", " ", value, ";"];
}
return [varSpec.identifier, ":", " ", value];
}
/**
* The TypeScript target-specific built-ins generator for generating the code that allows for the use of built-in
* functions.
* @since 0.10.0
*/
export class JavaScriptTargetBuiltInGenerator extends KipperTargetBuiltInGenerator {
async numToStr(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const convArgIdentifier = signature.params[0];
return genJSFunction(signature, `{ return (${convArgIdentifier}).toString(); }`);
}
async boolToStr(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const convArgIdentifier = signature.params[0];
return genJSFunction(signature, `{ return \`\${${convArgIdentifier}}\`; }`);
}
async voidToStr(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
return genJSFunction(signature, `{ return "void"; }`, true);
}
async nullToStr(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
return genJSFunction(signature, `{ return "null"; }`, true);
}
async undefinedToStr(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
return genJSFunction(signature, `{ return "undefined"; }`, true);
}
async strToNum(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const convArgIdentifier = signature.params[0];
return genJSFunction(signature, `{ return parseInt(${convArgIdentifier}); }`);
}
async boolToNum(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const convArgIdentifier = signature.params[0];
return genJSFunction(signature, `{ return ${convArgIdentifier} ? 1 : 0; }`);
}
async slice(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const objLikeIdentifier = signature.params[0];
const startIdentifier = signature.params[1];
const endIdentifier = signature.params[2];
return genJSFunction(
signature,
`{ return ${objLikeIdentifier} ? ${objLikeIdentifier}.slice(${startIdentifier}, ${endIdentifier}) : ${objLikeIdentifier}; }`,
);
}
async index(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const arrayLikeIdentifier = signature.params[0];
const indexIdentifier = signature.params[1];
return genJSFunction(
signature,
`{ if (${indexIdentifier} >= ${arrayLikeIdentifier}.length) ` +
`throw new __kipper.IndexError(\`Index '\${${indexIdentifier}}' out of bonds of array-like.\`); ` +
`return ${arrayLikeIdentifier}[${indexIdentifier}]; }`,
);
}
async repeatString(funcSpec: InternalFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const toRepeatIdentifier = signature.params[0];
const timesIdentifier = signature.params[1];
return genJSFunction(signature, `{ return ${toRepeatIdentifier}.repeat(${timesIdentifier}); }`);
}
async print(funcSpec: BuiltInFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const printArgIdentifier = signature.params[0];
// Define the function signature and its body. We will simply use 'console.log(msg)' for printing out IO.
return genJSFunction(signature, `{ console.log(${printArgIdentifier}); }`);
}
async len(funcSpec: BuiltInFunction): Promise<Array<TranslatedCodeLine>> {
const signature = getJSFunctionSignature(funcSpec);
const lenArgIdentifier = signature.params[0];
return genJSFunction(signature, `{ return ${lenArgIdentifier}.length; }`);
}
async __name__(varSpec: BuiltInVariable, programCtx: KipperProgramContext): Promise<Array<TranslatedCodeLine>> {
return [genJSVariable(varSpec, `"${programCtx.fileName}"`)];
}
async NaN(varSpec: BuiltInVariable): Promise<Array<TranslatedCodeLine>> {
return [genJSVariable(varSpec, "NaN")];
}
}