import {ExpressionContext, ConstructDescription } from "../../compilation/contexts" import { CPPConstruct, SuccessfullyCompiled, RuntimeConstruct } from "../CPPConstruct"; import { ASTNode } from "../../../ast/ASTNode"; import { Value } from "../../runtime/Value"; import { Int, ExpressionType, VoidType, CompleteObjectType, ReferenceType } from "../../compilation/types"; import { assert } from "../../../util/util"; import { Expression, ValueCategory, VCResultTypes, t_TypedExpression } from "./Expression"; import { RuntimeExpression } from "./RuntimeExpression"; import { OpaqueExpressionOutlet } from "../../../view/constructs/ExpressionOutlets"; import { ConstructOutlet } from "../../../view/constructs/ConstructOutlet"; import { LocalObjectEntity, LocalReferenceEntity } from "../../compilation/entities"; import { CompiledTemporaryDeallocator } from "../TemporaryDeallocator"; import { OpaqueExpressionASTNode } from "../../../ast/ast_expressions"; export type OpaqueExpressionImpl = { type: T | ((context: ExpressionContext) => T), valueCategory: VC, upNext?: (rt: RuntimeOpaqueExpression) => void operate: (rt: RuntimeOpaqueExpression) => T extends VoidType ? void : VCResultTypes, } const OPAQUE_EXPRESSIONS : {[index: string]: OpaqueExpressionImpl} = { // "test": { // type: VoidType.VOID, // valueCategory: "prvalue", // operate: (rt: RuntimeOpaqueExpression) => { rt.sim.cout(new Value(10, Int.INT)); } // } }; export function registerOpaqueExpression(id: string, impl: OpaqueExpressionImpl) { assert(!OPAQUE_EXPRESSIONS[id]); OPAQUE_EXPRESSIONS[id] = impl; } export class OpaqueExpression extends Expression { public readonly construct_type = "opaque_expression"; public readonly type: T; public readonly valueCategory: VC; public readonly impl: OpaqueExpressionImpl; public static createFromAST(ast: OpaqueExpressionASTNode, context: ExpressionContext) { assert(OPAQUE_EXPRESSIONS[ast.id]); return new OpaqueExpression(context, OPAQUE_EXPRESSIONS[ast.id], ast); } public constructor(context: ExpressionContext, impl: OpaqueExpressionImpl, ast?: OpaqueExpressionASTNode) { super(context, undefined); this.impl = impl; if (typeof impl.type === "function") { this.type = impl.type(context); } else { this.type = impl.type; } this.valueCategory = impl.valueCategory; } public createDefaultOutlet(this: CompiledOpaqueExpression, element: JQuery, parent?: ConstructOutlet) { return new OpaqueExpressionOutlet(element, this, parent); } public isTailChild(child: CPPConstruct) { return { isTail: true }; } // TODO public describeEvalResult(depth: number): ConstructDescription { throw new Error("Method not implemented."); } } export interface TypedOpaqueExpression extends OpaqueExpression, t_TypedExpression { } export interface CompiledOpaqueExpression extends TypedOpaqueExpression, SuccessfullyCompiled { readonly temporaryDeallocator?: CompiledTemporaryDeallocator; // to match CompiledPotentialFullExpression structure } export class RuntimeOpaqueExpression extends RuntimeExpression> { public constructor(model: CompiledOpaqueExpression, parent: RuntimeConstruct) { super(model, parent); } protected upNextImpl() { this.model.impl.upNext && this.model.impl.upNext(this) } private isVoid() : this is RuntimeOpaqueExpression { return this.model.type.isVoidType(); } protected stepForwardImpl() { let result = this.model.impl.operate(this); if (!this.model.type.isVoidType()) { this.setEvalResult(>result); } this.startCleanup(); } }