Skip to content

Commit

Permalink
major (#663): Implemented runtime meta type assignment to runtime arr…
Browse files Browse the repository at this point in the history
…ays and functions
  • Loading branch information
lorenzholzbauer committed Jul 26, 2024
1 parent a3dcf89 commit baa7b98
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
* @since 0.10.0
*/
import type { PrimaryExpressionTypeSemantics } from "../primary-expression-type-semantics";
import type { ProcessedType } from "../../../../../semantics";
import type { BuiltInTypeArray, ProcessedType } from "../../../../../semantics";

/**
* Type semantics for AST Node {@link ArrayPrimaryExpression}.
* @since 0.10.0
*/
export interface ArrayPrimaryExpressionTypeSemantics extends PrimaryExpressionTypeSemantics {
/**
* The evaluated type of the array. This is always some variation of the {@link BuiltInTypeArray}.
*/
evaluatedType: BuiltInTypeArray;
/**
* The value type that each member of the array evaluates to.
* @since 0.12.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
* @since 0.11.0
*/
import type { ExpressionTypeSemantics } from "../../expression-type-semantics";
import type { ProcessedType } from "../../../../../semantics";
import type { BuiltInTypeFunc, ProcessedType } from "../../../../../semantics";

/**
* Type semantics for AST Node {@link LambdaExpression}.
* @since 0.11.0
*/
export interface LambdaPrimaryExpressionTypeSemantics extends ExpressionTypeSemantics {
/**
* The type of this lambda expression. This is always some variation of the {@link BuiltInTypeFunc}.
* @since 0.12.0
*/
evaluatedType: BuiltInTypeFunc;
/**
* The return type of the lambda expression.
* @since 0.11.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { CompoundStatement } from "../../../statements";
import type { IdentifierTypeSpecifierExpression } from "../../type-specifier-expression";
import { ParameterDeclaration } from "../../../declarations";
import { UnableToDetermineSemanticDataError } from "../../../../../../errors";
import { BuiltInTypes, LambdaScope } from "../../../../../semantics";
import { BuiltInTypeFunc, BuiltInTypes, LambdaScope } from "../../../../../semantics";

/**
* Lambda expression class, which represents a lambda expression in the AST.
Expand Down Expand Up @@ -156,16 +156,10 @@ export class LambdaPrimaryExpression
// Get the type that will be returned using the return type specifier
const returnType = semanticData.returnTypeSpecifier.getTypeSemanticData().storedType;
this.typeSemantics = {
evaluatedType: BuiltInTypes.Func.changeGenericTypeArguments([
{
identifier: "T",
type: semanticData.params.map((param) => param.getTypeSemanticData().storedType),
},
{
identifier: "R",
type: returnType,
},
]),
evaluatedType: new BuiltInTypeFunc(
semanticData.params.map((param) => param.getTypeSemanticData().storedType),
returnType,
),
returnType: returnType,
};

Expand Down
23 changes: 0 additions & 23 deletions kipper/target-js/src/built-in-runtime-types.ts

This file was deleted.

106 changes: 92 additions & 14 deletions kipper/target-js/src/code-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import type {
IncrementOrDecrementPostfixExpression,
IncrementOrDecrementUnaryExpression,
InterfaceDeclaration,
InterfaceMethodDeclaration,
InterfacePropertyDeclaration,
JumpStatement,
KipperProgramContext,
LambdaPrimaryExpression,
Expand Down Expand Up @@ -70,10 +68,11 @@ import {
IfStatement,
KipperTargetCodeGenerator,
VariableDeclaration,
InterfaceMethodDeclaration,
InterfacePropertyDeclaration,
} from "@kipper/core";
import { createJSFunctionSignature, getJSFunctionSignature, indentLines, removeBraces } from "./tools";
import { TargetJS, version } from "./index";
import { BuiltInRuntimeType } from "./built-in-runtime-types";
import type { ClassConstructorDeclaration } from "@kipper/core/lib/compiler/ast/nodes/declarations/type-declaration/class-declaration/class-member-declaration/class-constructor-declaration/class-constructor-declaration";

function removeBrackets(lines: Array<TranslatedCodeLine>) {
Expand Down Expand Up @@ -198,6 +197,55 @@ export class JavaScriptTargetCodeGenerator extends KipperTargetCodeGenerator {
return [];
};

protected generateInterfaceRuntimeTypeChecks = async (
node: InterfaceDeclaration,
): Promise<Array<TranslatedCodeLine>> => {
const semanticData = node.getSemanticData();
const interfaceName = semanticData.identifier;
const interfaceMembers = semanticData.members;
const identifier = "__intf_" + interfaceName;

let propertiesWithTypes = "";
let functionsWithTypes = "";
for (let member of interfaceMembers) {
if (member instanceof InterfacePropertyDeclaration) {
const property = member.getSemanticData();
const type = member.getTypeSemanticData();
const runtimeType = TargetJS.getRuntimeType(type.type);
propertiesWithTypes +=
`new ${TargetJS.getBuiltInIdentifier("Property")}` + `("${property.identifier}", ${runtimeType}),`;
}
if (member instanceof InterfaceMethodDeclaration) {
const method = member.getSemanticData();
const returnType = member.getTypeSemanticData();
const params = method.parameters.map((param) => {
return param.getTypeSemanticData().valueType;
});
const runtimeReturnType = TargetJS.getRuntimeType(returnType.type);
const runtimeParams = params.map((paramType) => {
return `__intf_${TargetJS.getRuntimeType(paramType)}`;
});
functionsWithTypes +=
`new ${TargetJS.getBuiltInIdentifier("Method")}` +
`("${method.identifier}", ${runtimeReturnType}, [${runtimeParams.join(",")}]),`;
}
}

let lines: Array<TranslatedCodeLine> = [
[
"const ",
identifier,
` = new ${TargetJS.internalObjectIdentifier}.Type("` + interfaceName + '"',
", [",
propertiesWithTypes,
"], [",
functionsWithTypes,
"])",
],
];
return lines;
};

/**
* Translates a {@link CompoundStatement} into the JavaScript language.
*/
Expand Down Expand Up @@ -457,7 +505,10 @@ export class JavaScriptTargetCodeGenerator extends KipperTargetCodeGenerator {
* Translates a {@link AssignmentExpression} into the JavaScript language.
*/
interfaceDeclaration = async (node: InterfaceDeclaration): Promise<Array<TranslatedCodeLine>> => {
return [];
const runtimeInterfaceType = await this.generateInterfaceRuntimeTypeChecks(node);
return [
...runtimeInterfaceType,
];
};

/**
Expand Down Expand Up @@ -566,13 +617,29 @@ export class JavaScriptTargetCodeGenerator extends KipperTargetCodeGenerator {
*/
arrayPrimaryExpression = async (node: ArrayPrimaryExpression): Promise<TranslatedExpression> => {
const values = node.getSemanticData().value;
const valueType = node.getTypeSemanticData().valueType;
const valueTypeIdentifier = TargetJS.getRuntimeType(valueType);

const translatedValues: Array<TranslatedExpression> = await Promise.all(
values.map(async (value, i) => {
const exp = await value.translateCtxAndChildren();
return [...exp, i + 1 === values.length ? "" : ", "];
}),
);
return ["[", ...translatedValues.flat(), "]"];

return [
TargetJS.getBuiltInIdentifier("assignTypeMeta"),
"(",
"[",
...translatedValues.flat(),
"]",
",",
TargetJS.getBuiltInIdentifier("builtIn.Array.changeGenericTypeArguments"),
"(",
`{T: ${valueTypeIdentifier}}`,
")",
")",
];
};

/**
Expand Down Expand Up @@ -960,6 +1027,7 @@ export class JavaScriptTargetCodeGenerator extends KipperTargetCodeGenerator {
const semanticData = node.getSemanticData();
const params = semanticData.params;
const body = semanticData.functionBody;
const funcType = node.getTypeSemanticData().evaluatedType;

// Generate the function signature
const translatedParams: TranslatedExpression = (
Expand All @@ -971,26 +1039,36 @@ export class JavaScriptTargetCodeGenerator extends KipperTargetCodeGenerator {
)
.map((param) => <TranslatedExpression>[...param.flat(), ", "])
.flat();
translatedParams.pop(); // Remove the last comma
// Remove the last comma
translatedParams.pop();

const translatedBody =
body instanceof Expression
? await body.translateCtxAndChildren()
: (await body.translateCtxAndChildren()).map((line) => <TranslatedExpression>[...line, "\n"]).flat();
const paramTypes = funcType.parameterTypes.map((type) => TargetJS.getRuntimeType(type.getCompilableType()));
const returnType = TargetJS.getRuntimeType(funcType.returnType.getCompilableType());

// Return the lambda function
return ["(", ...translatedParams, ") => ", ...translatedBody];
return [
TargetJS.getBuiltInIdentifier("assignTypeMeta"),
"(",
"(",
...translatedParams,
") => ",
...(body instanceof CompoundStatement ? translatedBody.slice() : translatedBody),
",",
TargetJS.getBuiltInIdentifier("builtIn.Func.changeGenericTypeArguments"),
"(",
`{T: [${paramTypes.join(",")}], R: ${returnType}}`,
")",
")",
];
};

typeofExpression = async (node: TypeofExpression): Promise<TranslatedExpression> => {
const semanticData = node.getSemanticData();
const operand = await semanticData.operand.translateCtxAndChildren();

return [
TargetJS.getBuiltInIdentifier("typeOf"),
"(",
...operand,
")",
];
return [TargetJS.getBuiltInIdentifier("typeOf"), "(", ...operand, ")"];
};
}
1 change: 0 additions & 1 deletion kipper/target-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export * from "./semantic-analyser";
export * from "./code-generator";
export * from "./built-in-generator";
export * from "./tools";
export * from "./built-in-runtime-types";

// eslint-disable-next-line no-unused-vars
export const name = "@kipper/target-js";
Expand Down
8 changes: 3 additions & 5 deletions kipper/target-js/src/target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { BuiltInVariable, KipperCompileTarget } from "@kipper/core";
import { JavaScriptTargetSemanticAnalyser } from "./semantic-analyser";
import { JavaScriptTargetCodeGenerator } from "./code-generator";
import { JavaScriptTargetBuiltInGenerator } from "./built-in-generator";
import type { BuiltInRuntimeType } from "./built-in-runtime-types";
import { builtInRuntimeTypes } from "./built-in-runtime-types";

/**
* The JavaScript translation target for the Kipper language.
Expand Down Expand Up @@ -117,12 +115,12 @@ export class KipperJavaScriptTarget extends KipperCompileTarget {
}

/**
* Gets the builtin type for a Kipper Compiler Type
* Gets the builtin type for a Kipper type.
* @since 0.12.0
*/
public static getRuntimeType(type: ProcessedType): BuiltInRuntimeType | string {
public static getRuntimeType(type: ProcessedType): string {
if (type instanceof BuiltInType) {
return builtInRuntimeTypes.find((t) => t.name.toLowerCase() === type.identifier.toLowerCase()) ?? type.identifier;
return this.getBuiltInIdentifier(`builtIn.${type.identifier}`);
}
return type.identifier;
}
Expand Down
Loading

0 comments on commit baa7b98

Please sign in to comment.