Transform object literal expressions

This commit is contained in:
joeduffy 2017-01-12 13:38:54 -08:00
parent 1572816861
commit 24c4f48b81
3 changed files with 64 additions and 23 deletions

View file

@ -44,7 +44,7 @@ export interface StringLiteral extends Literal {
export const stringLiteralKind = "StringLiteral"; export const stringLiteralKind = "StringLiteral";
export type StringLiteralKind = "StringLiteral"; export type StringLiteralKind = "StringLiteral";
// A array literal (`new` and/or initialization). // A array literal plus optional initialization.
export interface ArrayLiteral extends Literal { export interface ArrayLiteral extends Literal {
kind: ArrayLiteralKind; kind: ArrayLiteralKind;
type: symbols.TypeToken; // the type of array to produce. type: symbols.TypeToken; // the type of array to produce.
@ -54,24 +54,23 @@ export interface ArrayLiteral extends Literal {
export const arrayLiteralKind = "ArrayLiteral"; export const arrayLiteralKind = "ArrayLiteral";
export type ArrayLiteralKind = "ArrayLiteral"; export type ArrayLiteralKind = "ArrayLiteral";
// An object literal (`new` and/or initialization). // An object literal plus optional initialization.
export interface ObjectLiteral extends Literal { export interface ObjectLiteral extends Literal {
kind: ObjectLiteralKind; kind: ObjectLiteralKind;
type: symbols.TypeToken; // the type of object to produce. type: symbols.TypeToken; // the type of object to produce.
initializers?: ObjectLiteralInitializer[]; // an optional array of property initializers. properties?: ObjectLiteralProperty[]; // an optional array of property initializers.
arguments?: Expression[]; // an optional set of arguments for the constructor.
} }
export const objectLiteralKind = "ObjectLiteral"; export const objectLiteralKind = "ObjectLiteral";
export type ObjectLiteralKind = "ObjectLiteral"; export type ObjectLiteralKind = "ObjectLiteral";
// An object literal property initializer. // An object literal property initializer.
export interface ObjectLiteralInitializer extends Node { export interface ObjectLiteralProperty extends Node {
kind: ObjectLiteralInitializerKind; kind: ObjectLiteralPropertyKind;
property: symbols.VariableToken; // the property being initialized. name: Identifier; // the property being initialized.
value: Expression; // the expression value to store into the property. value: Expression; // the expression value to store into the property.
} }
export const objectLiteralInitializerKind = "ObjectLiteralInitializer"; export const objectLiteralPropertyKind = "ObjectLiteralProperty";
export type ObjectLiteralInitializerKind = "ObjectLiteralInitializer"; export type ObjectLiteralPropertyKind = "ObjectLiteralProperty";
/** Loads **/ /** Loads **/

View file

@ -49,7 +49,7 @@ export type NodeKind =
expressions.StringLiteralKind | expressions.StringLiteralKind |
expressions.ArrayLiteralKind | expressions.ArrayLiteralKind |
expressions.ObjectLiteralKind | expressions.ObjectLiteralKind |
expressions.ObjectLiteralInitializerKind | expressions.ObjectLiteralPropertyKind |
expressions.LoadLocationExpressionKind | expressions.LoadLocationExpressionKind |
expressions.LoadDynamicExpressionKind | expressions.LoadDynamicExpressionKind |
expressions.NewExpressionKind | expressions.NewExpressionKind |

View file

@ -1178,7 +1178,7 @@ export class Transformer {
} }
} }
private transformArrayLiteralExpression(node: ts.ArrayLiteralExpression): ast.Expression { private transformArrayLiteralExpression(node: ts.ArrayLiteralExpression): ast.ArrayLiteral {
return this.withLocation(node, <ast.ArrayLiteral>{ return this.withLocation(node, <ast.ArrayLiteral>{
kind: ast.arrayLiteralKind, kind: ast.arrayLiteralKind,
type: this.transformTypeNode(undefined), type: this.transformTypeNode(undefined),
@ -1293,21 +1293,63 @@ export class Transformer {
return contract.fail("NYI"); return contract.fail("NYI");
} }
private transformObjectLiteralExpression(node: ts.ObjectLiteralExpression): ast.Expression { private transformObjectLiteralExpression(node: ts.ObjectLiteralExpression): ast.ObjectLiteral {
return contract.fail("NYI"); // TODO[marapongo/mu#46]: because TypeScript object literals are untyped, it's not clear what MuIL type this
// expression should produce. It's common for a TypeScript literal to be enclosed in a cast, for example,
// `<SomeType>{ literal }`, in which case, perhaps we could detect `<SomeType>`. Alternatively, MuIL could
// just automatically dynamically coerce `any` to the target type, similar to TypeScript, when necessary.
// I had envisioned requiring explicit dynamic casts for this, in which case, perhaps this expression should
// always be encased in something that prepares it for dynamic cast in the consuming expression.
return this.withLocation(node, <ast.ObjectLiteral>{
kind: ast.objectLiteralKind,
type: this.transformTypeNode(undefined),
properties: node.properties.map(
(prop: ts.ObjectLiteralElement) => this.transformObjectLiteralElement(prop)),
});
} }
private transformObjectLiteralElement(node: ts.ObjectLiteralElement): ast.Expression { private transformObjectLiteralElement(node: ts.ObjectLiteralElement): ast.ObjectLiteralProperty {
return contract.fail("NYI"); switch (node.kind) {
case ts.SyntaxKind.PropertyAssignment:
return this.transformObjectLiteralPropertyAssignment(<ts.PropertyAssignment>node);
case ts.SyntaxKind.ShorthandPropertyAssignment:
return this.transformObjectLiteralShorthandPropertyAssignment(<ts.ShorthandPropertyAssignment>node);
case ts.SyntaxKind.GetAccessor:
return this.transformObjectLiteralFunctionLikeElement(<ts.GetAccessorDeclaration>node);
case ts.SyntaxKind.SetAccessor:
return this.transformObjectLiteralFunctionLikeElement(<ts.SetAccessorDeclaration>node);
case ts.SyntaxKind.MethodDeclaration:
return this.transformObjectLiteralFunctionLikeElement(<ts.MethodDeclaration>node);
default:
return contract.fail(`Unrecognized object literal element kind ${ts.SyntaxKind[node.kind]}`);
}
} }
private transformObjectLiteralPropertyElement( private transformObjectLiteralPropertyAssignment(node: ts.PropertyAssignment): ast.ObjectLiteralProperty {
node: ts.PropertyAssignment | ts.ShorthandPropertyAssignment): ast.Expression { return this.withLocation(node, <ast.ObjectLiteralProperty>{
return contract.fail("NYI"); kind: ast.objectLiteralPropertyKind,
name: this.transformPropertyName(node.name),
value: this.transformExpression(node.initializer),
});
} }
private transformObjectLiteralFunctionLikeElement( private transformObjectLiteralShorthandPropertyAssignment(
node: ts.AccessorDeclaration | ts.MethodDeclaration): ast.Expression { node: ts.ShorthandPropertyAssignment): ast.ObjectLiteralProperty {
let name: ast.Identifier = this.transformIdentifier(node.name);
return this.withLocation(node, <ast.ObjectLiteralProperty>{
kind: ast.objectLiteralPropertyKind,
name: name,
value: this.withLocation(node.name, <ast.LoadLocationExpression>{
kind: ast.loadLocationExpressionKind,
name: name,
}),
});
}
private transformObjectLiteralFunctionLikeElement(node: ts.FunctionLikeDeclaration): ast.ObjectLiteralProperty {
// TODO: turn these into lambdas.
return contract.fail("NYI"); return contract.fail("NYI");
} }