Map new expressions
This change adds a new AST node kind to represent "new" expressions. Originally I had thought we could simply represent these as calls to a constructor, however, there is a sizeable semantic difference and so it's better for this node kind to be distinct; for example, we will most likely permit allocation of objects without explicit constructors. In addition, I've added a "complex" scenario test, which is just a Point class. It has a constructor, two properties, and an instance method that performs arithmetic and allocates a new instance. It works!
This commit is contained in:
parent
00e0c00ac9
commit
2d5ec61aeb
|
@ -91,12 +91,23 @@ export type LoadDynamicExpressionKind = "LoadDynamicExpression";
|
|||
|
||||
/** Functions **/
|
||||
|
||||
// Invokes a function.
|
||||
export interface InvokeFunctionExpression extends Expression {
|
||||
kind: InvokeFunctionExpressionKind;
|
||||
function: Expression; // a function to invoke (of a func type).
|
||||
export interface CallExpression extends Expression {
|
||||
arguments?: Expression[]; // the list of arguments in sequential order.
|
||||
}
|
||||
|
||||
// Allocates a new object and calls its constructor.
|
||||
export interface NewExpression extends CallExpression {
|
||||
kind: NewExpressionKind;
|
||||
type: Identifier; // the object type to allocate.
|
||||
}
|
||||
export const newExpressionKind = "NewExpression";
|
||||
export type NewExpressionKind = "NewExpression";
|
||||
|
||||
// Invokes a function.
|
||||
export interface InvokeFunctionExpression extends CallExpression {
|
||||
kind: InvokeFunctionExpressionKind;
|
||||
function: Expression; // a function to invoke (of a func type).
|
||||
}
|
||||
export const invokeFunctionExpressionKind = "InvokeFunctionExpression";
|
||||
export type InvokeFunctionExpressionKind = "InvokeFunctionExpression";
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ export type NodeKind =
|
|||
expressions.ObjectLiteralInitializerKind |
|
||||
expressions.LoadLocationExpressionKind |
|
||||
expressions.LoadDynamicExpressionKind |
|
||||
expressions.NewExpressionKind |
|
||||
expressions.InvokeFunctionExpressionKind |
|
||||
expressions.LambdaExpressionKind |
|
||||
expressions.UnaryOperatorExpressionKind |
|
||||
|
|
|
@ -1241,8 +1241,21 @@ export class Transpiler {
|
|||
});
|
||||
}
|
||||
|
||||
private transformNewExpression(node: ts.NewExpression): ast.Expression {
|
||||
return contract.fail("NYI");
|
||||
private transformNewExpression(node: ts.NewExpression): ast.NewExpression {
|
||||
// Only "new T(..)" constructors, where T is an identifier referring to a type, are permitted.
|
||||
let ty: ast.Identifier;
|
||||
if (node.expression.kind === ts.SyntaxKind.Identifier) {
|
||||
ty = this.transformIdentifier(<ts.Identifier>node.expression);
|
||||
}
|
||||
else {
|
||||
return contract.fail("New T(..) expression must have an identifier T");
|
||||
}
|
||||
|
||||
return <ast.NewExpression>{
|
||||
kind: ast.newExpressionKind,
|
||||
type: ty,
|
||||
arguments: node.arguments.map((expr: ts.Expression) => this.transformExpression(expr)),
|
||||
};
|
||||
}
|
||||
|
||||
private transformOmittedExpression(node: ts.OmittedExpression): ast.Expression {
|
||||
|
|
|
@ -20,6 +20,9 @@ let testCases: string[] = [
|
|||
"modules/func_exp_def_1",
|
||||
"modules/class_1",
|
||||
"modules/class_exp_1",
|
||||
|
||||
// These are not quite real-world-code, but they are more complex "integration" style tests.
|
||||
"scenarios/point",
|
||||
];
|
||||
|
||||
describe("outputs", () => {
|
||||
|
|
4
tools/mujs/tests/output/scenarios/point/Mu.json
Normal file
4
tools/mujs/tests/output/scenarios/point/Mu.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "scenarios/point"
|
||||
}
|
||||
|
678
tools/mujs/tests/output/scenarios/point/Mu.out.json
Normal file
678
tools/mujs/tests/output/scenarios/point/Mu.out.json
Normal file
|
@ -0,0 +1,678 @@
|
|||
{
|
||||
"name": "scenarios/point",
|
||||
"modules": {
|
||||
"index": {
|
||||
"kind": "Module",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "index"
|
||||
},
|
||||
"members": {
|
||||
"Point": {
|
||||
"kind": "Class",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "Point",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 13
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 18
|
||||
}
|
||||
}
|
||||
},
|
||||
"access": "public",
|
||||
"members": {
|
||||
".ctor": {
|
||||
"kind": "ClassMethod",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": ".ctor"
|
||||
},
|
||||
"access": "public",
|
||||
"parameters": [
|
||||
{
|
||||
"kind": "LocalVariable",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "x",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 16
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 17
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "TODO"
|
||||
},
|
||||
{
|
||||
"kind": "LocalVariable",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "y",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 27
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 28
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "TODO"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"kind": "Block",
|
||||
"statements": [
|
||||
{
|
||||
"kind": "ExpressionStatement",
|
||||
"expression": {
|
||||
"kind": "BinaryOperatorExpression",
|
||||
"operator": "=",
|
||||
"left": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"object": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": ".this"
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "x",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 13
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 14
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 14
|
||||
}
|
||||
}
|
||||
},
|
||||
"right": {
|
||||
"kind": "Identifier",
|
||||
"ident": "x",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 18
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 18
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 9,
|
||||
"column": 19
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "ExpressionStatement",
|
||||
"expression": {
|
||||
"kind": "BinaryOperatorExpression",
|
||||
"operator": "=",
|
||||
"left": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"object": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": ".this"
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "y",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 13
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 14
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 14
|
||||
}
|
||||
}
|
||||
},
|
||||
"right": {
|
||||
"kind": "Identifier",
|
||||
"ident": "y",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 18
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 18
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 10,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 19
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 38
|
||||
},
|
||||
"end": {
|
||||
"line": 11,
|
||||
"column": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"returnType": "TODO",
|
||||
"static": false,
|
||||
"abstract": false,
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 11,
|
||||
"column": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"add": {
|
||||
"kind": "ClassMethod",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "add",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 13,
|
||||
"column": 11
|
||||
},
|
||||
"end": {
|
||||
"line": 13,
|
||||
"column": 14
|
||||
}
|
||||
}
|
||||
},
|
||||
"access": "public",
|
||||
"parameters": [
|
||||
{
|
||||
"kind": "LocalVariable",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "other",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 13,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 13,
|
||||
"column": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "TODO"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"kind": "Block",
|
||||
"statements": [
|
||||
{
|
||||
"kind": "ReturnStatement",
|
||||
"expression": {
|
||||
"kind": "NewExpression",
|
||||
"type": {
|
||||
"kind": "Identifier",
|
||||
"ident": "Point",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 24
|
||||
}
|
||||
}
|
||||
},
|
||||
"arguments": [
|
||||
{
|
||||
"kind": "BinaryOperatorExpression",
|
||||
"operator": "+",
|
||||
"left": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"object": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": ".this"
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 25
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 29
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "x",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 30
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 31
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 25
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 31
|
||||
}
|
||||
}
|
||||
},
|
||||
"right": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"object": {
|
||||
"kind": "Identifier",
|
||||
"ident": "other",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 34
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 39
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "x",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 40
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 41
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 34
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 41
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 25
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 41
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "BinaryOperatorExpression",
|
||||
"operator": "+",
|
||||
"left": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"object": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": ".this"
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 43
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 47
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "y",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 48
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 49
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 43
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 49
|
||||
}
|
||||
}
|
||||
},
|
||||
"right": {
|
||||
"kind": "LoadLocationExpression",
|
||||
"object": {
|
||||
"kind": "Identifier",
|
||||
"ident": "other",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 52
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 57
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "y",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 58
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 59
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 52
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 59
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 43
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 59
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 14,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 14,
|
||||
"column": 61
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 13,
|
||||
"column": 36
|
||||
},
|
||||
"end": {
|
||||
"line": 15,
|
||||
"column": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"returnType": "TODO",
|
||||
"static": false,
|
||||
"abstract": false,
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 13,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 15,
|
||||
"column": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"x": {
|
||||
"kind": "ClassProperty",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "x",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 5,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 21
|
||||
}
|
||||
}
|
||||
},
|
||||
"access": "public",
|
||||
"readonly": true,
|
||||
"static": false,
|
||||
"type": "TODO"
|
||||
},
|
||||
"y": {
|
||||
"kind": "ClassProperty",
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"ident": "y",
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 6,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 21
|
||||
}
|
||||
}
|
||||
},
|
||||
"access": "public",
|
||||
"readonly": true,
|
||||
"static": false,
|
||||
"type": "TODO"
|
||||
}
|
||||
},
|
||||
"abstract": false,
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 16,
|
||||
"column": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"loc": {
|
||||
"file": "index.ts",
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 18,
|
||||
"column": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
tools/mujs/tests/output/scenarios/point/index.ts
Normal file
17
tools/mujs/tests/output/scenarios/point/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
// This is a simple test case that exports a class with a number of interesting facets: namely, a constructor, some
|
||||
// member variables, and some member methods.
|
||||
|
||||
export class Point {
|
||||
public readonly x: number;
|
||||
public readonly y: number;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public add(other: Point): Point {
|
||||
return new Point(this.x + other.x, this.y + other.y);
|
||||
}
|
||||
}
|
||||
|
6
tools/mujs/tests/output/scenarios/point/tsconfig.json
Normal file
6
tools/mujs/tests/output/scenarios/point/tsconfig.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"files": [
|
||||
"index.ts"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in a new issue