MichaReiser/speedy.js

View on GitHub
packages/compiler/src/code-generation/runtime-system-name-mangler.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as assert from "assert";
import * as ts from "typescript";
import {CompilationContext} from "../compilation-context";
import {BaseNameMangler} from "./base-name-mangler";
import {Parameter} from "./name-mangler";

/**
 * Name mangler for functions implemented in the Runtime
 *
 * Functions of the runtime systems have no prefix. It is left to the runtime implementor to guarantee that there are
 * no conflicting names between the runtime and the llvm intrinsics.
 *
 * The name of a function is the declared name of the function including the encoded argument types. The following encoding is used for arguments
 * boolean:     b
 * int:         i
 * number:      d
 * Object:      Pv
 * Array:       Pti where t is the encoded element type
 *
 * Functions accepting varargs or an array parameter need to have two arguments in the runtime implementation. The first
 * is a pointer to an array of the elements. The second is an int that defines the number of elements in the array.
 *
 * Functions belonging to a class are prefixed with the class name. The class and function name is separated by an underscore. If
 * the class itself is generic (e.g. Array), than the generic arguments are appended to the class name.
 *
 * Examples:
 * isNaN(number): isNaNd
 * isNaN(int): isNaNi
 *
 * Array<int>.push(): ArrayIi_pushPii
 * Array<int>.push(3): ArrayIb_pushPii
 *
 * Array<int>.fill(3): ArrayIi_filli
 * Array<int>.fill(3, 2): ArrayIi_fillii
 */
export class RuntimeSystemNameMangler extends BaseNameMangler {

    private arraySymbol: ts.Symbol | undefined;

    constructor(compilationContext: CompilationContext) {
        super(compilationContext);
        this.arraySymbol = compilationContext.builtIns.get("Array");
    }

    get separator() {
        return "_";
    }

    getModulePrefix() {
        return "";
    }

    protected getParameterTypeCode(parameter: Parameter) {
        if (parameter.variadic) {
            assert(parameter.type.getSymbol() === this.arraySymbol, "Vararg should be ArrayType");
            const elementType = (parameter.type as ts.GenericType).typeArguments[0];
            return `P${this.typeToCode(elementType)}u`;
        }

        return super.getParameterTypeCode(parameter);
    }

    protected typeToCode(type: ts.Type) {
        if (type.flags & ts.TypeFlags.Object) {
            return "Pv";
        }

        return super.typeToCode(type);
    }

    protected encodeName(name: string): string {
        return name;
    }
}