Generic function type aliases

This commit is contained in:
dcodeIO 2018-03-12 17:44:09 +01:00
parent 423533c6b0
commit 7870e3ac18
14 changed files with 380 additions and 470 deletions

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -902,6 +902,7 @@ export abstract class Node {
static createTypeDeclaration(
name: IdentifierExpression,
typeParameters: TypeParameterNode[] | null,
alias: CommonTypeNode,
modifiers: ModifierNode[] | null,
decorators: DecoratorNode[] | null,
@ -910,7 +911,8 @@ export abstract class Node {
var stmt = new TypeDeclaration();
stmt.range = range;
stmt.name = name; name.parent = stmt;
stmt.alias = alias; alias.parent = stmt;
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
stmt.type = alias; alias.parent = stmt;
stmt.modifiers = modifiers; if (modifiers) setParent(modifiers, stmt);
stmt.decorators = decorators; if (decorators) setParent(decorators, stmt);
return stmt;
@ -1728,8 +1730,10 @@ export class TryStatement extends Statement {
export class TypeDeclaration extends DeclarationStatement {
kind = NodeKind.TYPEDECLARATION;
/** Type parameters, if any. */
typeParameters: TypeParameterNode[] | null;
/** Type being aliased. */
alias: CommonTypeNode;
type: CommonTypeNode;
}
/** Represents a variable declaration part of a {@link VariableStatement}. */

View File

@ -81,24 +81,24 @@ import {
import {
CharCode
} from "../util/charcode";
import { Signature } from "../types";
export function serializeNode(node: Node, sb: string[]): void {
switch (node.kind) {
case NodeKind.SOURCE:
case NodeKind.SOURCE: {
serializeSource(<Source>node, sb);
break;
}
// types
case NodeKind.TYPE:
case NodeKind.TYPE: {
serializeTypeNode(<TypeNode>node, sb);
break;
case NodeKind.TYPEPARAMETER:
}
case NodeKind.TYPEPARAMETER: {
serializeTypeParameter(<TypeParameterNode>node, sb);
break;
}
// expressions
@ -108,202 +108,206 @@ export function serializeNode(node: Node, sb: string[]): void {
case NodeKind.THIS:
case NodeKind.TRUE:
case NodeKind.CONSTRUCTOR:
case NodeKind.IDENTIFIER:
case NodeKind.IDENTIFIER: {
serializeIdentifierExpression(<IdentifierExpression>node, sb);
break;
case NodeKind.ASSERTION:
}
case NodeKind.ASSERTION: {
serializeAssertionExpression(<AssertionExpression>node, sb);
break;
case NodeKind.BINARY:
}
case NodeKind.BINARY: {
serializeBinaryExpression(<BinaryExpression>node, sb);
break;
case NodeKind.CALL:
}
case NodeKind.CALL: {
serializeCallExpression(<CallExpression>node, sb);
break;
case NodeKind.ELEMENTACCESS:
}
case NodeKind.ELEMENTACCESS: {
serializeElementAccessExpression(<ElementAccessExpression>node, sb);
break;
}
case NodeKind.FUNCTION:
case NodeKind.FUNCTIONARROW:
case NodeKind.FUNCTIONARROW: {
serializeFunctionExpression(<FunctionExpression>node, sb);
break;
case NodeKind.LITERAL:
}
case NodeKind.LITERAL: {
serializeLiteralExpression(<LiteralExpression>node, sb);
break;
case NodeKind.NEW:
}
case NodeKind.NEW: {
serializeNewExpression(<NewExpression>node, sb);
break;
case NodeKind.PARENTHESIZED:
}
case NodeKind.PARENTHESIZED: {
serializeParenthesizedExpression(<ParenthesizedExpression>node, sb);
break;
case NodeKind.PROPERTYACCESS:
}
case NodeKind.PROPERTYACCESS: {
serializePropertyAccessExpression(<PropertyAccessExpression>node, sb);
break;
case NodeKind.TERNARY:
}
case NodeKind.TERNARY: {
serializeTernaryExpression(<TernaryExpression>node, sb);
break;
case NodeKind.UNARYPOSTFIX:
}
case NodeKind.UNARYPOSTFIX: {
serializeUnaryPostfixExpression(<UnaryPostfixExpression>node, sb);
break;
case NodeKind.UNARYPREFIX:
}
case NodeKind.UNARYPREFIX: {
serializeUnaryPrefixExpression(<UnaryPrefixExpression>node, sb);
break;
}
// statements
case NodeKind.BLOCK:
case NodeKind.BLOCK: {
serializeBlockStatement(<BlockStatement>node, sb);
break;
case NodeKind.BREAK:
}
case NodeKind.BREAK: {
serializeBreakStatement(<BreakStatement>node, sb);
break;
case NodeKind.CONTINUE:
}
case NodeKind.CONTINUE: {
serializeContinueStatement(<ContinueStatement>node, sb);
break;
case NodeKind.DO:
}
case NodeKind.DO: {
serializeDoStatement(<DoStatement>node, sb);
break;
case NodeKind.EMPTY:
}
case NodeKind.EMPTY: {
serializeEmptyStatement(<EmptyStatement>node, sb);
break;
case NodeKind.EXPORT:
}
case NodeKind.EXPORT: {
serializeExportStatement(<ExportStatement>node, sb);
break;
case NodeKind.EXPORTIMPORT:
}
case NodeKind.EXPORTIMPORT: {
serializeExportImportStatement(<ExportImportStatement>node, sb);
break;
case NodeKind.EXPRESSION:
}
case NodeKind.EXPRESSION: {
serializeExpressionStatement(<ExpressionStatement>node, sb);
break;
case NodeKind.FOR:
}
case NodeKind.FOR: {
serializeForStatement(<ForStatement>node, sb);
break;
case NodeKind.IF:
}
case NodeKind.IF: {
serializeIfStatement(<IfStatement>node, sb);
break;
case NodeKind.IMPORT:
}
case NodeKind.IMPORT: {
serializeImportStatement(<ImportStatement>node, sb);
break;
case NodeKind.RETURN:
}
case NodeKind.RETURN: {
serializeReturnStatement(<ReturnStatement>node, sb);
break;
case NodeKind.SWITCH:
}
case NodeKind.SWITCH: {
serializeSwitchStatement(<SwitchStatement>node, sb);
break;
case NodeKind.THROW:
}
case NodeKind.THROW: {
serializeThrowStatement(<ThrowStatement>node, sb);
break;
case NodeKind.TRY:
}
case NodeKind.TRY: {
serializeTryStatement(<TryStatement>node, sb);
break;
case NodeKind.VARIABLE:
}
case NodeKind.VARIABLE: {
serializeVariableStatement(<VariableStatement>node, sb);
break;
case NodeKind.WHILE:
}
case NodeKind.WHILE: {
serializeWhileStatement(<WhileStatement>node, sb);
break;
}
// declaration statements
case NodeKind.CLASSDECLARATION:
case NodeKind.CLASSDECLARATION: {
serializeClassDeclaration(<ClassDeclaration>node, sb);
break;
case NodeKind.ENUMDECLARATION:
}
case NodeKind.ENUMDECLARATION: {
serializeEnumDeclaration(<EnumDeclaration>node, sb);
break;
case NodeKind.ENUMVALUEDECLARATION:
}
case NodeKind.ENUMVALUEDECLARATION: {
serializeEnumValueDeclaration(<EnumValueDeclaration>node, sb);
break;
case NodeKind.FIELDDECLARATION:
}
case NodeKind.FIELDDECLARATION: {
serializeFieldDeclaration(<FieldDeclaration>node, sb);
break;
case NodeKind.FUNCTIONDECLARATION:
}
case NodeKind.FUNCTIONDECLARATION: {
serializeFunctionDeclaration(<FunctionDeclaration>node, sb);
break;
case NodeKind.IMPORTDECLARATION:
}
case NodeKind.IMPORTDECLARATION: {
serializeImportDeclaration(<ImportDeclaration>node, sb);
break;
case NodeKind.INTERFACEDECLARATION:
}
case NodeKind.INTERFACEDECLARATION: {
serializeInterfaceDeclaration(<InterfaceDeclaration>node, sb);
break;
case NodeKind.METHODDECLARATION:
}
case NodeKind.METHODDECLARATION: {
serializeMethodDeclaration(<MethodDeclaration>node, sb);
break;
case NodeKind.NAMESPACEDECLARATION:
}
case NodeKind.NAMESPACEDECLARATION: {
serializeNamespaceDeclaration(<NamespaceDeclaration>node, sb);
break;
case NodeKind.TYPEDECLARATION:
}
case NodeKind.TYPEDECLARATION: {
serializeTypeDeclaration(<TypeDeclaration>node, sb);
break;
case NodeKind.VARIABLEDECLARATION:
}
case NodeKind.VARIABLEDECLARATION: {
serializeVariableDeclaration(<VariableDeclaration>node, sb);
break;
}
// other
case NodeKind.DECORATOR:
case NodeKind.DECORATOR: {
serializeDecorator(<DecoratorNode>node, sb);
break;
case NodeKind.EXPORTMEMBER:
}
case NodeKind.EXPORTMEMBER: {
serializeExportMember(<ExportMember>node, sb);
break;
case NodeKind.MODIFIER:
}
case NodeKind.MODIFIER: {
serializeModifier(<ModifierNode>node, sb);
break;
case NodeKind.PARAMETER:
}
case NodeKind.PARAMETER: {
serializeParameter(<ParameterNode>node, sb);
break;
case NodeKind.SWITCHCASE:
}
case NodeKind.SWITCHCASE: {
serializeSwitchCase(<SwitchCase>node, sb);
break;
default:
}
default: {
assert(false);
break;
}
}
}
export function serializeSource(source: Source, sb: string[]): void {
for (var i = 0, k = source.statements.length; i < k; ++i) {
@ -315,7 +319,8 @@ export function serializeSource(source: Source, sb: string[]): void {
export function serializeTypeNode(node: CommonTypeNode, sb: string[]): void {
if (node.kind == NodeKind.SIGNATURE) {
return serializeSignatureNode(<SignatureNode>node, sb);
serializeSignatureNode(<SignatureNode>node, sb);
return;
}
var typeNode = <TypeNode>node;
serializeIdentifierExpression(<IdentifierExpression>typeNode.name, sb);
@ -473,36 +478,36 @@ export function serializeFunctionExpression(node: FunctionExpression, sb: string
export function serializeLiteralExpression(node: LiteralExpression, sb: string[]): void {
switch (node.literalKind) {
case LiteralKind.FLOAT:
case LiteralKind.FLOAT: {
serializeFloatLiteralExpression(<FloatLiteralExpression>node, sb);
break;
case LiteralKind.INTEGER:
}
case LiteralKind.INTEGER: {
serializeIntegerLiteralExpression(<IntegerLiteralExpression>node, sb);
break;
case LiteralKind.STRING:
}
case LiteralKind.STRING: {
serializeStringLiteralExpression(<StringLiteralExpression>node, sb);
break;
case LiteralKind.REGEXP:
}
case LiteralKind.REGEXP: {
serializeRegexpLiteralExpression(<RegexpLiteralExpression>node, sb);
break;
case LiteralKind.ARRAY:
}
case LiteralKind.ARRAY: {
serializeArrayLiteralExpression(<ArrayLiteralExpression>node, sb);
break;
// case LiteralKind.OBJECT:
}
// case LiteralKind.OBJECT: {
// serializeObjectLiteralExpression(<ObjectLiteralExpression>node, sb);
// break;
default:
// }
default: {
assert(false);
break;
}
}
}
export function serializeFloatLiteralExpression(node: FloatLiteralExpression, sb: string[]): void {
sb.push(node.value.toString(10));
@ -518,50 +523,49 @@ export function serializeStringLiteral(str: string, sb: string[], singleQuoted:
sb.push(quote);
for (var i = 0, k = str.length; i < k;) {
switch (str.charCodeAt(i)) {
case CharCode.NULL:
case CharCode.NULL: {
if (i > off) sb.push(str.substring(off, off = i + 1));
sb.push("\\0");
off = ++i;
break;
case CharCode.BACKSPACE:
}
case CharCode.BACKSPACE: {
if (i > off) sb.push(str.substring(off, i));
off = ++i;
sb.push("\\b");
break;
case CharCode.TAB:
}
case CharCode.TAB: {
if (i > off) sb.push(str.substring(off, i));
off = ++i;
sb.push("\\t");
break;
case CharCode.LINEFEED:
}
case CharCode.LINEFEED: {
if (i > off) sb.push(str.substring(off, i));
off = ++i;
sb.push("\\n");
break;
case CharCode.VERTICALTAB:
}
case CharCode.VERTICALTAB: {
if (i > off) sb.push(str.substring(off, i));
off = ++i;
sb.push("\\v");
break;
case CharCode.FORMFEED:
}
case CharCode.FORMFEED: {
if (i > off) sb.push(str.substring(off, i));
off = ++i;
sb.push("\\f");
break;
case CharCode.CARRIAGERETURN:
}
case CharCode.CARRIAGERETURN: {
if (i > off) sb.push(str.substring(off, i));
sb.push("\\r");
off = ++i;
break;
case CharCode.DOUBLEQUOTE:
}
case CharCode.DOUBLEQUOTE: {
if (!singleQuoted) {
if (i > off) sb.push(str.substring(off, i));
sb.push("\\\"");
@ -570,8 +574,8 @@ export function serializeStringLiteral(str: string, sb: string[], singleQuoted:
++i;
}
break;
case CharCode.SINGLEQUOTE:
}
case CharCode.SINGLEQUOTE: {
if (singleQuoted) {
if (i > off) sb.push(str.substring(off, i));
sb.push("\\'");
@ -580,18 +584,19 @@ export function serializeStringLiteral(str: string, sb: string[], singleQuoted:
++i;
}
break;
case CharCode.BACKSLASH:
}
case CharCode.BACKSLASH: {
if (i > off) sb.push(str.substring(off, i));
sb.push("\\\\");
off = ++i;
break;
default:
}
default: {
++i;
break;
}
}
}
if (i > off) sb.push(str.substring(off, i));
sb.push(quote);
}
@ -634,18 +639,15 @@ export function serializeTernaryExpression(node: TernaryExpression, sb: string[]
export function serializeUnaryExpression(node: UnaryExpression, sb: string[]): void {
switch (node.kind) {
case NodeKind.UNARYPOSTFIX:
case NodeKind.UNARYPOSTFIX: {
serializeUnaryPostfixExpression(<UnaryPostfixExpression>node, sb);
break;
case NodeKind.UNARYPREFIX:
}
case NodeKind.UNARYPREFIX: {
serializeUnaryPrefixExpression(<UnaryPrefixExpression>node, sb);
break;
default:
assert(false);
break;
}
default: assert(false);
}
}
@ -1178,8 +1180,16 @@ export function serializeTypeDeclaration(node: TypeDeclaration, sb: string[]): v
}
sb.push("type ");
serializeIdentifierExpression(node.name, sb);
var typeParameters = node.typeParameters;
if (typeParameters && (k = typeParameters.length)) {
sb.push("<");
for (i = 0; i < k; ++i) {
serializeTypeParameter(typeParameters[i], sb);
}
sb.push(">");
}
sb.push(" = ");
serializeTypeNode(node.alias, sb);
serializeTypeNode(node.type, sb);
}
export function serializeVariableDeclaration(node: VariableDeclaration, sb: string[]): void {
@ -1207,24 +1217,24 @@ export function serializeVariableStatement(node: VariableStatement, sb: string[]
for (i = 0, k = node.modifiers.length; i < k; ++i) {
var modifier = node.modifiers[i];
switch (modifier.modifierKind) {
case ModifierKind.CONST:
case ModifierKind.CONST: {
assert(!isLet);
isConst = true;
break;
case ModifierKind.LET:
}
case ModifierKind.LET: {
assert(!isConst);
isLet = true;
break;
default:
}
default: {
serializeModifier(modifier, sb);
sb.push(" ");
break;
}
}
}
}
sb.push(isConst ? "const " : isLet ? "let " : "var ");
k = assert(node.declarations.length);
serializeVariableDeclaration(node.declarations[0], sb);
@ -1301,6 +1311,9 @@ export function modifierToString(node: ModifierNode): string {
case ModifierKind.READONLY: return "readonly";
case ModifierKind.GET: return "get";
case ModifierKind.SET: return "set";
default: assert(false); return "";
default: {
assert(false);
return "";
}
}
}

View File

@ -1979,7 +1979,7 @@ export class Parser extends DiagnosticEmitter {
return this.parseTryStatement(tn);
}
case Token.TYPE: {
return this.parseTypeDeclaration(tn, null);
return this.parseTypeDeclaration(tn);
}
case Token.VOID: {
return this.parseVoidStatement(tn);
@ -2429,17 +2429,29 @@ export class Parser extends DiagnosticEmitter {
decorators: DecoratorNode[] | null = null
): TypeDeclaration | null {
// at 'type': Identifier '=' Type ';'?
// at 'type': Identifier ('<' TypeParameters '>')? '=' Type ';'?
var startPos = decorators && decorators.length ? decorators[0].range.start
: modifiers && modifiers.length ? modifiers[0].range.start
: tn.tokenPos;
if (tn.skip(Token.IDENTIFIER)) {
var name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
var typeParameters: TypeParameterNode[] | null = null;
if (tn.skip(Token.LESSTHAN)) {
typeParameters = this.parseTypeParameters(tn);
if (!typeParameters) return null;
}
if (tn.skip(Token.EQUALS)) {
var type = this.parseType(tn);
if (!type) return null;
var ret = Node.createTypeDeclaration(name, type, modifiers, decorators, tn.range(startPos, tn.pos));
var ret = Node.createTypeDeclaration(
name,
typeParameters,
type,
modifiers,
decorators,
tn.range(startPos, tn.pos)
);
tn.skip(Token.SEMICOLON);
return ret;
} else {

View File

@ -102,6 +102,12 @@ class QueuedImport {
declaration: ImportDeclaration;
}
/** Represents a type alias. */
class TypeAlias {
typeParameters: TypeParameterNode[] | null;
type: CommonTypeNode;
}
const noTypesYet = new Map<string,Type>();
/** Represents an AssemblyScript program. */
@ -118,7 +124,7 @@ export class Program extends DiagnosticEmitter {
/** Types by internal name. */
types: Map<string,Type> = noTypesYet;
/** Declared type aliases. */
typeAliases: Map<string,CommonTypeNode> = new Map();
typeAliases: Map<string,TypeAlias> = new Map();
/** Exports of individual files by exported name. Not global exports. */
exports: Map<string,Element> = new Map();
@ -1257,7 +1263,10 @@ export class Program extends DiagnosticEmitter {
);
return;
}
this.typeAliases.set(name, declaration.alias);
var alias = new TypeAlias();
alias.typeParameters = declaration.typeParameters;
alias.type = declaration.type;
this.typeAliases.set(name, alias);
}
private initializeVariables(statement: VariableStatement, namespace: Element | null = null): void {
@ -1386,8 +1395,9 @@ export class Program extends DiagnosticEmitter {
return Type.u32.asFunction(signature);
}
var typeNode = <TypeNode>node;
var globalName = typeNode.name.text;
var localName = typeNode.range.source.internalPath + PATH_DELIMITER + typeNode.name.text;
var simpleName = typeNode.name.text;
var globalName = simpleName;
var localName = typeNode.range.source.internalPath + PATH_DELIMITER + simpleName;
var element: Element | null;
@ -1405,6 +1415,10 @@ export class Program extends DiagnosticEmitter {
}
}
// check (global) type alias
var alias = this.typeAliases.get(simpleName);
if (alias) return this.resolveType(alias.type, contextualTypeArguments, reportNotFound);
// resolve parameters
if (typeNode.typeArguments) {
var k = typeNode.typeArguments.length;
@ -1438,12 +1452,6 @@ export class Program extends DiagnosticEmitter {
return type;
}
// check type alias
var alias = this.typeAliases.get(globalName);
if (alias && (type = this.resolveType(alias, null, reportNotFound))) {
return type;
}
if (reportNotFound) {
this.error(
DiagnosticCode.Cannot_find_name_0,

View File

@ -2,18 +2,12 @@
(type $ii (func (param i32) (result i32)))
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $v (func))
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $fff (func (param f32 f32) (result f32)))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $function-expression/f1 (mut i32) (i32.const 0))
(global $function-expression/f2 (mut i32) (i32.const 1))
(global $function-expression/f3 (mut i32) (i32.const 2))
(global $function-expression/i32Adder (mut i32) (i32.const 0))
(global $function-expression/f32Adder (mut i32) (i32.const 0))
(global $function-expression/i8Adder (mut i32) (i32.const 0))
(table 6 6 anyfunc)
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|0 $start~someName|2 $function-expression/makeAdder<i32>~theAdder|3 $function-expression/makeAdder<f32>~theAdder|4 $function-expression/makeAdderArrow<i8>~anonymous|5)
(table 3 3 anyfunc)
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|0 $start~someName|2)
(memory $0 1)
(data (i32.const 4) "\16\00\00\00f\00u\00n\00c\00t\00i\00o\00n\00-\00e\00x\00p\00r\00e\00s\00s\00i\00o\00n\00.\00t\00s")
(export "memory" (memory $0))
@ -24,40 +18,7 @@
(func $start~someName|2 (; 2 ;) (type $v)
(nop)
)
(func $function-expression/makeAdder<i32>~theAdder|3 (; 3 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(get_local $0)
(get_local $1)
)
)
(func $function-expression/makeAdder<i32> (; 4 ;) (type $i) (result i32)
(i32.const 3)
)
(func $function-expression/makeAdder<f32>~theAdder|4 (; 5 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
(f32.add
(get_local $0)
(get_local $1)
)
)
(func $function-expression/makeAdder<f32> (; 6 ;) (type $i) (result i32)
(i32.const 4)
)
(func $function-expression/makeAdderArrow<i8>~anonymous|5 (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(i32.shr_s
(i32.shl
(i32.add
(get_local $0)
(get_local $1)
)
(i32.const 24)
)
(i32.const 24)
)
)
(func $function-expression/makeAdderArrow<i8> (; 8 ;) (type $i) (result i32)
(i32.const 5)
)
(func $start (; 9 ;) (type $v)
(func $start (; 3 ;) (type $v)
(if
(i32.ne
(call_indirect (type $ii)
@ -97,92 +58,5 @@
(call_indirect (type $v)
(get_global $function-expression/f3)
)
(set_global $function-expression/i32Adder
(call $function-expression/makeAdder<i32>)
)
(if
(i32.ne
(call_indirect (type $iii)
(i32.const 4)
(i32.const 2)
(get_global $function-expression/i32Adder)
)
(i32.const 6)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 22)
(i32.const 0)
)
(unreachable)
)
)
(set_global $function-expression/f32Adder
(call $function-expression/makeAdder<f32>)
)
(if
(f32.ne
(call_indirect (type $fff)
(f32.const 1.5)
(f32.const 2.5)
(get_global $function-expression/f32Adder)
)
(f32.const 4)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 25)
(i32.const 0)
)
(unreachable)
)
)
(set_global $function-expression/i8Adder
(call $function-expression/makeAdderArrow<i8>)
)
(if
(i32.ne
(call_indirect (type $iii)
(i32.const 127)
(i32.const 127)
(get_global $function-expression/i8Adder)
)
(i32.const -2)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 34)
(i32.const 0)
)
(unreachable)
)
)
(set_global $function-expression/f1
(get_global $function-expression/f2)
)
(if
(i32.ne
(call_indirect (type $ii)
(i32.const 4)
(get_global $function-expression/f1)
)
(i32.const 4)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 37)
(i32.const 0)
)
(unreachable)
)
)
)
)

View File

@ -11,27 +11,3 @@ assert(f2(2) == 2);
var f3 = function someName(): void {
};
f3();
function makeAdder<T>(): (a: T, b: T) => T {
return function theAdder(a: T, b: T): T {
return a + b;
};
}
var i32Adder = makeAdder<i32>();
assert(i32Adder(4, 2) == 6);
var f32Adder = makeAdder<f32>();
assert(f32Adder(1.5, 2.5) == 4.0);
function makeAdderArrow<T>(): (a: T, b: T) => T {
return (a: T, b: T): T => {
return a + b;
};
}
var i8Adder = makeAdderArrow<i8>();
assert(i8Adder(127, 127) == -2);
f1 = f2;
assert(f1(4) == 4);

View File

@ -2,19 +2,13 @@
(type $ii (func (param i32) (result i32)))
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $v (func))
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $fff (func (param f32 f32) (result f32)))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $function-expression/f1 (mut i32) (i32.const 0))
(global $function-expression/f2 (mut i32) (i32.const 1))
(global $function-expression/f3 (mut i32) (i32.const 2))
(global $function-expression/i32Adder (mut i32) (i32.const 0))
(global $function-expression/f32Adder (mut i32) (i32.const 0))
(global $function-expression/i8Adder (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 52))
(table 6 6 anyfunc)
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|1 $start~someName|2 $function-expression/makeAdder<i32>~theAdder|3 $function-expression/makeAdder<f32>~theAdder|4 $function-expression/makeAdderArrow<i8>~anonymous|5)
(table 3 3 anyfunc)
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|1 $start~someName|2)
(memory $0 1)
(data (i32.const 4) "\16\00\00\00f\00u\00n\00c\00t\00i\00o\00n\00-\00e\00x\00p\00r\00e\00s\00s\00i\00o\00n\00.\00t\00s\00")
(export "memory" (memory $0))
@ -31,52 +25,7 @@
)
(func $start~someName|2 (; 3 ;) (type $v)
)
(func $function-expression/makeAdder<i32>~theAdder|3 (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(return
(i32.add
(get_local $0)
(get_local $1)
)
)
)
(func $function-expression/makeAdder<i32> (; 5 ;) (type $i) (result i32)
(return
(i32.const 3)
)
)
(func $function-expression/makeAdder<f32>~theAdder|4 (; 6 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
(return
(f32.add
(get_local $0)
(get_local $1)
)
)
)
(func $function-expression/makeAdder<f32> (; 7 ;) (type $i) (result i32)
(return
(i32.const 4)
)
)
(func $function-expression/makeAdderArrow<i8>~anonymous|5 (; 8 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(return
(i32.shr_s
(i32.shl
(i32.add
(get_local $0)
(get_local $1)
)
(i32.const 24)
)
(i32.const 24)
)
)
)
(func $function-expression/makeAdderArrow<i8> (; 9 ;) (type $i) (result i32)
(return
(i32.const 5)
)
)
(func $start (; 10 ;) (type $v)
(func $start (; 4 ;) (type $v)
(if
(i32.eqz
(i32.eq
@ -120,100 +69,5 @@
(call_indirect (type $v)
(get_global $function-expression/f3)
)
(set_global $function-expression/i32Adder
(call $function-expression/makeAdder<i32>)
)
(if
(i32.eqz
(i32.eq
(call_indirect (type $iii)
(i32.const 4)
(i32.const 2)
(get_global $function-expression/i32Adder)
)
(i32.const 6)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 22)
(i32.const 0)
)
(unreachable)
)
)
(set_global $function-expression/f32Adder
(call $function-expression/makeAdder<f32>)
)
(if
(i32.eqz
(f32.eq
(call_indirect (type $fff)
(f32.const 1.5)
(f32.const 2.5)
(get_global $function-expression/f32Adder)
)
(f32.const 4)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 25)
(i32.const 0)
)
(unreachable)
)
)
(set_global $function-expression/i8Adder
(call $function-expression/makeAdderArrow<i8>)
)
(if
(i32.eqz
(i32.eq
(call_indirect (type $iii)
(i32.const 127)
(i32.const 127)
(get_global $function-expression/i8Adder)
)
(i32.const -2)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 34)
(i32.const 0)
)
(unreachable)
)
)
(set_global $function-expression/f1
(get_global $function-expression/f2)
)
(if
(i32.eqz
(i32.eq
(call_indirect (type $ii)
(i32.const 4)
(get_global $function-expression/f1)
)
(i32.const 4)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 37)
(i32.const 0)
)
(unreachable)
)
)
)
)

View File

@ -0,0 +1,66 @@
(module
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $III (func (param i64 i64) (result i64)))
(type $FFF (func (param f64 f64) (result f64)))
(type $v (func))
(global $function-types/i32Adder (mut i32) (i32.const 0))
(global $function-types/i64Adder (mut i32) (i32.const 0))
(table 3 3 anyfunc)
(elem (i32.const 0) $function-types/makeAdder<i32>~anonymous|0 $function-types/makeAdder<i64>~anonymous|1 $function-types/makeAdder<f64>~anonymous|2)
(memory $0 1)
(export "memory" (memory $0))
(start $start)
(func $function-types/makeAdder<i32>~anonymous|0 (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(get_local $0)
(get_local $1)
)
)
(func $function-types/makeAdder<i32> (; 1 ;) (type $i) (result i32)
(i32.const 0)
)
(func $function-types/makeAdder<i64>~anonymous|1 (; 2 ;) (type $III) (param $0 i64) (param $1 i64) (result i64)
(i64.add
(get_local $0)
(get_local $1)
)
)
(func $function-types/makeAdder<i64> (; 3 ;) (type $i) (result i32)
(i32.const 1)
)
(func $function-types/makeAdder<f64>~anonymous|2 (; 4 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
(f64.add
(get_local $0)
(get_local $1)
)
)
(func $function-types/makeAdder<f64> (; 5 ;) (type $i) (result i32)
(i32.const 2)
)
(func $start (; 6 ;) (type $v)
(set_global $function-types/i32Adder
(call $function-types/makeAdder<i32>)
)
(drop
(call_indirect (type $iii)
(i32.const 1)
(i32.const 2)
(get_global $function-types/i32Adder)
)
)
(set_global $function-types/i64Adder
(call $function-types/makeAdder<i64>)
)
(drop
(call_indirect (type $III)
(i64.const 1)
(i64.const 2)
(get_global $function-types/i64Adder)
)
)
(drop
(call $function-types/makeAdder<f64>)
)
)
)

View File

@ -0,0 +1,15 @@
type Adder<T> = (a: T, b: T) => T;
function makeAdder<T>(): Adder<T> {
return (a: T, b: T): T => {
return a + b;
};
}
var i32Adder = makeAdder<i32>();
i32Adder(1, 2);
var i64Adder = makeAdder<i64>();
i64Adder(1, 2);
makeAdder<f64>()(1, 2);

View File

@ -0,0 +1,88 @@
(module
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $III (func (param i64 i64) (result i64)))
(type $FFF (func (param f64 f64) (result f64)))
(type $v (func))
(global $function-types/i32Adder (mut i32) (i32.const 0))
(global $function-types/i64Adder (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 4))
(table 3 3 anyfunc)
(elem (i32.const 0) $function-types/makeAdder<i32>~anonymous|0 $function-types/makeAdder<i64>~anonymous|1 $function-types/makeAdder<f64>~anonymous|2)
(memory $0 1)
(export "memory" (memory $0))
(start $start)
(func $function-types/makeAdder<i32>~anonymous|0 (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(return
(i32.add
(get_local $0)
(get_local $1)
)
)
)
(func $function-types/makeAdder<i32> (; 1 ;) (type $i) (result i32)
(return
(i32.const 0)
)
)
(func $function-types/makeAdder<i64>~anonymous|1 (; 2 ;) (type $III) (param $0 i64) (param $1 i64) (result i64)
(return
(i64.add
(get_local $0)
(get_local $1)
)
)
)
(func $function-types/makeAdder<i64> (; 3 ;) (type $i) (result i32)
(return
(i32.const 1)
)
)
(func $function-types/makeAdder<f64>~anonymous|2 (; 4 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
(return
(f64.add
(get_local $0)
(get_local $1)
)
)
)
(func $function-types/makeAdder<f64> (; 5 ;) (type $i) (result i32)
(return
(i32.const 2)
)
)
(func $start (; 6 ;) (type $v)
(nop)
(set_global $function-types/i32Adder
(call $function-types/makeAdder<i32>)
)
(drop
(call_indirect (type $iii)
(i32.const 1)
(i32.const 2)
(get_global $function-types/i32Adder)
)
)
(set_global $function-types/i64Adder
(call $function-types/makeAdder<i64>)
)
(drop
(call_indirect (type $III)
(i64.const 1)
(i64.const 2)
(get_global $function-types/i64Adder)
)
)
(drop
(call $function-types/makeAdder<f64>)
)
(block
(drop
(i32.const 1)
)
(drop
(i32.const 2)
)
)
)
)