mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Progress
This commit is contained in:
parent
d1c1178f25
commit
d3d4938b68
6
package-lock.json
generated
6
package-lock.json
generated
@ -41,9 +41,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"binaryen": {
|
"binaryen": {
|
||||||
"version": "37.0.0-nightly.20170912",
|
"version": "39.0.0-nightly.20171116",
|
||||||
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-37.0.0-nightly.20170912.tgz",
|
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-39.0.0-nightly.20171116.tgz",
|
||||||
"integrity": "sha512-yXLgHkUvTMqEV1vkixAaldnS4w6WOrqY+30Cx9k+JjBzmA6wJTQr0F32xFg/4MPr4NRZOdP/AnI8ais4nhfgIw=="
|
"integrity": "sha512-ljl/qPne0+8hYtNWITRSAtxNM1EG5NnvTg+HRmSUdNAK2j9wcyAAg5uVj+TgipEqY82kmHt5C9+TSQNEwaxgrw=="
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^8.0.28",
|
"@types/node": "^8.0.28",
|
||||||
"binaryen": "37.0.0-nightly.20170912"
|
"binaryen": "39.0.0-nightly.20171116"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc -P src",
|
||||||
|
"test:compiler": "ts-node -P src tests/compiler"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1091,7 +1091,7 @@ export class Source extends Node {
|
|||||||
tokenizer: Tokenizer | null = null;
|
tokenizer: Tokenizer | null = null;
|
||||||
isEntry: bool;
|
isEntry: bool;
|
||||||
|
|
||||||
constructor(path: string, text: string, isEntry: bool) {
|
constructor(path: string, text: string, isEntry: bool = false) {
|
||||||
super();
|
super();
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.normalizedPath = normalizePath(path, true);
|
this.normalizedPath = normalizePath(path, true);
|
||||||
@ -1392,6 +1392,7 @@ export class ExpressionStatement extends Statement {
|
|||||||
|
|
||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
this.expression.serialize(sb);
|
this.expression.serialize(sb);
|
||||||
|
sb.push(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1773,6 +1774,7 @@ export class ThrowStatement extends Statement {
|
|||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push("throw ");
|
sb.push("throw ");
|
||||||
this.expression.serialize(sb);
|
this.expression.serialize(sb);
|
||||||
|
sb.push(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1895,10 +1897,11 @@ export function serialize(node: Node, indent: i32 = 0): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function mangleInternalPath(path: string): string {
|
export function mangleInternalPath(path: string): string {
|
||||||
if (PATH_DELIMITER.charCodeAt(0) != CharCode.SLASH)
|
// TODO: not necessary with current config
|
||||||
|
/* if (PATH_DELIMITER.charCodeAt(0) != CharCode.SLASH)
|
||||||
path = path.replace("/", PATH_DELIMITER);
|
path = path.replace("/", PATH_DELIMITER);
|
||||||
if (PARENT_SUBST != "..")
|
if (PARENT_SUBST != "..")
|
||||||
path = path.replace("..", PARENT_SUBST);
|
path = path.replace("..", PARENT_SUBST); */
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
74
src/binaryen.d.ts
vendored
74
src/binaryen.d.ts
vendored
@ -15,7 +15,7 @@ declare function _free(ptr: usize): void;
|
|||||||
|
|
||||||
declare type BinaryenIndex = u32;
|
declare type BinaryenIndex = u32;
|
||||||
|
|
||||||
declare type BinaryenType = u32;
|
declare type BinaryenType = i32;
|
||||||
|
|
||||||
declare function _BinaryenNone(): BinaryenType;
|
declare function _BinaryenNone(): BinaryenType;
|
||||||
declare function _BinaryenInt32(): BinaryenType;
|
declare function _BinaryenInt32(): BinaryenType;
|
||||||
@ -24,6 +24,37 @@ declare function _BinaryenFloat32(): BinaryenType;
|
|||||||
declare function _BinaryenFloat64(): BinaryenType;
|
declare function _BinaryenFloat64(): BinaryenType;
|
||||||
declare function _BinaryenUndefined(): BinaryenType;
|
declare function _BinaryenUndefined(): BinaryenType;
|
||||||
|
|
||||||
|
declare type BinaryenExpressionId = i32;
|
||||||
|
|
||||||
|
declare function _BinaryenInvalidId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenBlockId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenIfId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenLoopId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenBreakId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenSwitchId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenCallId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenCallImportId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenCallIndirectId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenGetLocalId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenSetLocalId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenGetGlobalId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenSetGlobalId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenLoadId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenStoreId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenConstId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenUnaryId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenBinaryId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenSelectId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenDropId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenReturnId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenHostId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenNopId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenUnreachableId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenAtomicCmpxchgId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenAtomicRMWId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenAtomicWaitId(): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenAtomicWakeId(): BinaryenExpressionId;
|
||||||
|
|
||||||
declare type BinaryenModuleRef = usize;
|
declare type BinaryenModuleRef = usize;
|
||||||
|
|
||||||
declare function _BinaryenModuleCreate(): BinaryenModuleRef;
|
declare function _BinaryenModuleCreate(): BinaryenModuleRef;
|
||||||
@ -34,10 +65,11 @@ declare type CString = usize;
|
|||||||
declare type CArray<T> = usize;
|
declare type CArray<T> = usize;
|
||||||
|
|
||||||
declare function _BinaryenAddFunctionType(module: BinaryenModuleRef, name: CString, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
|
declare function _BinaryenAddFunctionType(module: BinaryenModuleRef, name: CString, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
|
||||||
|
declare function _BinaryenGetFunctionTypeBySignature(module: BinaryenModuleRef, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
|
||||||
|
|
||||||
declare type BinaryenLiteral = CArray<u8>;
|
declare type BinaryenLiteral = CArray<u8>;
|
||||||
|
|
||||||
// LLVM C ABI with `out` being a buffer of 16 bytes receiving the BinaryenLiteral struct
|
// LLVM C ABI with `out` being a buffer of 16 bytes receiving the BinaryenLiteral struct.
|
||||||
// union value starts at offset 8 due to alignment (?)
|
// union value starts at offset 8 due to alignment (?)
|
||||||
declare function _BinaryenLiteralInt32(out: BinaryenLiteral, x: i32): void;
|
declare function _BinaryenLiteralInt32(out: BinaryenLiteral, x: i32): void;
|
||||||
declare function _BinaryenLiteralInt64(out: BinaryenLiteral, x: i32, y: i32): void;
|
declare function _BinaryenLiteralInt64(out: BinaryenLiteral, x: i32, y: i32): void;
|
||||||
@ -171,10 +203,22 @@ declare function _BinaryenLtFloat64(): BinaryenOp;
|
|||||||
declare function _BinaryenLeFloat64(): BinaryenOp;
|
declare function _BinaryenLeFloat64(): BinaryenOp;
|
||||||
declare function _BinaryenGtFloat64(): BinaryenOp;
|
declare function _BinaryenGtFloat64(): BinaryenOp;
|
||||||
declare function _BinaryenGeFloat64(): BinaryenOp;
|
declare function _BinaryenGeFloat64(): BinaryenOp;
|
||||||
declare function _BinaryenPageSize(): BinaryenOp;
|
|
||||||
declare function _BinaryenCurrentMemory(): BinaryenOp;
|
declare type BinaryenHostOp = BinaryenOp;
|
||||||
declare function _BinaryenGrowMemory(): BinaryenOp;
|
|
||||||
declare function _BinaryenHasFeature(): BinaryenOp;
|
declare function _BinaryenPageSize(): BinaryenHostOp;
|
||||||
|
declare function _BinaryenCurrentMemory(): BinaryenHostOp;
|
||||||
|
declare function _BinaryenGrowMemory(): BinaryenHostOp;
|
||||||
|
declare function _BinaryenHasFeature(): BinaryenHostOp;
|
||||||
|
|
||||||
|
declare type BinaryenAtomicRMWOp = BinaryenOp;
|
||||||
|
|
||||||
|
declare function _BinaryenAtomicRMWAdd(): BinaryenAtomicRMWOp;
|
||||||
|
declare function _BinaryenAtomicRMWSub(): BinaryenAtomicRMWOp;
|
||||||
|
declare function _BinaryenAtomicRMWAnd(): BinaryenAtomicRMWOp;
|
||||||
|
declare function _BinaryenAtomicRMWOr(): BinaryenAtomicRMWOp;
|
||||||
|
declare function _BinaryenAtomicRMWXor(): BinaryenAtomicRMWOp;
|
||||||
|
declare function _BinaryenAtomicRMWXchg(): BinaryenAtomicRMWOp;
|
||||||
|
|
||||||
declare type BinaryenExpressionRef = usize;
|
declare type BinaryenExpressionRef = usize;
|
||||||
|
|
||||||
@ -202,8 +246,19 @@ declare function _BinaryenReturn(module: BinaryenModuleRef, value: BinaryenExpre
|
|||||||
declare function _BinaryenHost(module: BinaryenModuleRef, op: BinaryenOp, name: CString | 0, operands: CArray<BinaryenExpressionRef>, numOperands: BinaryenIndex): BinaryenExpressionRef;
|
declare function _BinaryenHost(module: BinaryenModuleRef, op: BinaryenOp, name: CString | 0, operands: CArray<BinaryenExpressionRef>, numOperands: BinaryenIndex): BinaryenExpressionRef;
|
||||||
declare function _BinaryenNop(module: BinaryenModuleRef): BinaryenExpressionRef;
|
declare function _BinaryenNop(module: BinaryenModuleRef): BinaryenExpressionRef;
|
||||||
declare function _BinaryenUnreachable(module: BinaryenModuleRef): BinaryenExpressionRef;
|
declare function _BinaryenUnreachable(module: BinaryenModuleRef): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenAtomicRMW(module: BinaryenModuleRef, op: BinaryenAtomicRMWOp, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenAtomicCmpxchg(module: BinaryenModuleRef, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, replacement: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenAtomicWait(module: BinaryenModuleRef, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, timeout: BinaryenExpressionRef, expectedType: BinaryenType): BinaryenExpressionRef;
|
||||||
|
declare function _BinaryenAtomicWake(module: BinaryenModuleRef, ptr: BinaryenExpressionRef, wakeCount: BinaryenExpressionRef): BinaryenExpressionRef;
|
||||||
|
|
||||||
|
declare function _BinaryenExpressionGetId(expr: BinaryenExpressionRef): BinaryenExpressionId;
|
||||||
|
declare function _BinaryenExpressionGetType(expr: BinaryenExpressionRef): BinaryenType;
|
||||||
declare function _BinaryenExpressionPrint(expr: BinaryenExpressionRef): void;
|
declare function _BinaryenExpressionPrint(expr: BinaryenExpressionRef): void;
|
||||||
|
declare function _BinaryenConstGetValueI32(expr: BinaryenExpressionRef): i32;
|
||||||
|
declare function _BinaryenConstGetValueI64Low(expr: BinaryenExpressionRef): i32;
|
||||||
|
declare function _BinaryenConstGetValueI64High(expr: BinaryenExpressionRef): i32;
|
||||||
|
declare function _BinaryenConstGetValueF32(expr: BinaryenExpressionRef): f32;
|
||||||
|
declare function _BinaryenConstGetValueF64(expr: BinaryenExpressionRef): f64;
|
||||||
|
|
||||||
declare type BinaryenFunctionRef = usize;
|
declare type BinaryenFunctionRef = usize;
|
||||||
|
|
||||||
@ -219,7 +274,9 @@ declare type BinaryenExportRef = usize;
|
|||||||
declare function _BinaryenAddExport(module: BinaryenModuleRef, internalName: CString, externalName: CString): BinaryenExportRef;
|
declare function _BinaryenAddExport(module: BinaryenModuleRef, internalName: CString, externalName: CString): BinaryenExportRef;
|
||||||
declare function _BinaryenRemoveExport(module: BinaryenModuleRef, externalName: CString): void;
|
declare function _BinaryenRemoveExport(module: BinaryenModuleRef, externalName: CString): void;
|
||||||
|
|
||||||
declare function _BinaryenAddGlobal(module: BinaryenModuleRef, name: CString, type: BinaryenType, mutable: i8, init: BinaryenExpressionRef): BinaryenImportRef; // sic
|
declare type BinaryenGlobalRef = usize;
|
||||||
|
|
||||||
|
declare function _BinaryenAddGlobal(module: BinaryenModuleRef, name: CString, type: BinaryenType, mutable: i8, init: BinaryenExpressionRef): BinaryenGlobalRef;
|
||||||
|
|
||||||
declare function _BinaryenSetFunctionTable(module: BinaryenModuleRef, funcs: CArray<BinaryenFunctionRef>, numFuncs: BinaryenIndex): void;
|
declare function _BinaryenSetFunctionTable(module: BinaryenModuleRef, funcs: CArray<BinaryenFunctionRef>, numFuncs: BinaryenIndex): void;
|
||||||
|
|
||||||
@ -232,6 +289,7 @@ declare function _BinaryenModulePrint(module: BinaryenModuleRef): void;
|
|||||||
declare function _BinaryenModulePrintAsmjs(module: BinaryenModuleRef): void;
|
declare function _BinaryenModulePrintAsmjs(module: BinaryenModuleRef): void;
|
||||||
declare function _BinaryenModuleValidate(module: BinaryenModuleRef): i32;
|
declare function _BinaryenModuleValidate(module: BinaryenModuleRef): i32;
|
||||||
declare function _BinaryenModuleOptimize(module: BinaryenModuleRef): void;
|
declare function _BinaryenModuleOptimize(module: BinaryenModuleRef): void;
|
||||||
|
declare function _BinaryenModuleRunPasses(module: BinaryenModuleRef, passes: string[]): void;
|
||||||
declare function _BinaryenModuleAutoDrop(module: BinaryenModuleRef): void;
|
declare function _BinaryenModuleAutoDrop(module: BinaryenModuleRef): void;
|
||||||
declare function _BinaryenModuleWrite(module: BinaryenModuleRef, output: CString, outputSize: usize): usize;
|
declare function _BinaryenModuleWrite(module: BinaryenModuleRef, output: CString, outputSize: usize): usize;
|
||||||
declare function _BinaryenModuleRead(input: CString, inputSize: usize): BinaryenModuleRef;
|
declare function _BinaryenModuleRead(input: CString, inputSize: usize): BinaryenModuleRef;
|
||||||
@ -248,5 +306,3 @@ declare function _RelooperAddBranchForSwitch(from: RelooperBlockRef, to: Reloope
|
|||||||
declare function _RelooperRenderAndDispose(relooper: RelooperRef, entry: RelooperBlockRef, labelHelper: BinaryenIndex, module: BinaryenModuleRef): BinaryenExpressionRef;
|
declare function _RelooperRenderAndDispose(relooper: RelooperRef, entry: RelooperBlockRef, labelHelper: BinaryenIndex, module: BinaryenModuleRef): BinaryenExpressionRef;
|
||||||
|
|
||||||
declare function _BinaryenSetAPITracing(on: i32): void;
|
declare function _BinaryenSetAPITracing(on: i32): void;
|
||||||
|
|
||||||
declare function _BinaryenGetFunctionTypeBySignature(module: BinaryenModuleRef, result: BinaryenType, paramTypes: CArray<BinaryenType>, numParams: BinaryenIndex): BinaryenFunctionTypeRef;
|
|
||||||
|
136
src/binaryen.ts
136
src/binaryen.ts
@ -1,4 +1,4 @@
|
|||||||
import { U64 } from "./util";
|
import { I64, U64 } from "./util";
|
||||||
import { Target } from "./compiler";
|
import { Target } from "./compiler";
|
||||||
|
|
||||||
export enum Type {
|
export enum Type {
|
||||||
@ -10,6 +10,37 @@ export enum Type {
|
|||||||
Undefined = _BinaryenUndefined()
|
Undefined = _BinaryenUndefined()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ExpressionId {
|
||||||
|
Invalid = _BinaryenInvalidId(),
|
||||||
|
Block = _BinaryenBlockId(),
|
||||||
|
If = _BinaryenIfId(),
|
||||||
|
Loop = _BinaryenLoopId(),
|
||||||
|
Break = _BinaryenBreakId(),
|
||||||
|
Switch = _BinaryenSwitchId(),
|
||||||
|
Call = _BinaryenCallId(),
|
||||||
|
CallImport = _BinaryenCallImportId(),
|
||||||
|
CallIndirect = _BinaryenCallIndirectId(),
|
||||||
|
GetLocal = _BinaryenGetLocalId(),
|
||||||
|
SetLocal = _BinaryenSetLocalId(),
|
||||||
|
GetGlobal = _BinaryenGetGlobalId(),
|
||||||
|
SetGlobal = _BinaryenSetGlobalId(),
|
||||||
|
Load = _BinaryenLoadId(),
|
||||||
|
Store = _BinaryenStoreId(),
|
||||||
|
Const = _BinaryenConstId(),
|
||||||
|
Unary = _BinaryenUnaryId(),
|
||||||
|
Binary = _BinaryenBinaryId(),
|
||||||
|
Select = _BinaryenSelectId(),
|
||||||
|
Drop = _BinaryenDropId(),
|
||||||
|
Return = _BinaryenReturnId(),
|
||||||
|
Host = _BinaryenHostId(),
|
||||||
|
Nop = _BinaryenNopId(),
|
||||||
|
Unreachable = _BinaryenUnreachableId(),
|
||||||
|
AtomicCmpxchg = _BinaryenAtomicCmpxchgId(),
|
||||||
|
AtomicRMW = _BinaryenAtomicRMWId(),
|
||||||
|
AtomicWait = _BinaryenAtomicWaitId(),
|
||||||
|
AtomicWake = _BinaryenAtomicWakeId()
|
||||||
|
}
|
||||||
|
|
||||||
export enum UnaryOp {
|
export enum UnaryOp {
|
||||||
ClzI32 = _BinaryenClzInt32(),
|
ClzI32 = _BinaryenClzInt32(),
|
||||||
CtzI32 = _BinaryenCtzInt32(),
|
CtzI32 = _BinaryenCtzInt32(),
|
||||||
@ -146,13 +177,13 @@ export enum HostOp {
|
|||||||
HasFeature = _BinaryenHasFeature()
|
HasFeature = _BinaryenHasFeature()
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AtomicRMWOp { // TODO: not yet part of the C-API
|
export enum AtomicRMWOp {
|
||||||
Add,
|
Add = _BinaryenAtomicRMWAdd(),
|
||||||
Sub,
|
Sub = _BinaryenAtomicRMWSub(),
|
||||||
And,
|
And = _BinaryenAtomicRMWAnd(),
|
||||||
Or,
|
Or = _BinaryenAtomicRMWOr(),
|
||||||
Xor,
|
Xor = _BinaryenAtomicRMWXor(),
|
||||||
Xchg
|
Xchg = _BinaryenAtomicRMWXchg()
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MemorySegment {
|
export class MemorySegment {
|
||||||
@ -216,8 +247,8 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenAddFunctionType(this.ref, cStr, result, cArr, paramTypes.length);
|
return _BinaryenAddFunctionType(this.ref, cStr, result, cArr, paramTypes.length);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr);
|
|
||||||
_free(cArr);
|
_free(cArr);
|
||||||
|
_free(cStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,8 +305,8 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenHost(this.ref, op, cStr, cArr, operands ? (<BinaryenExpressionRef[]>operands).length : 0);
|
return _BinaryenHost(this.ref, op, cStr, cArr, operands ? (<BinaryenExpressionRef[]>operands).length : 0);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr);
|
|
||||||
_free(cArr);
|
_free(cArr);
|
||||||
|
_free(cStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,6 +330,26 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createAtomicRMW(op: AtomicRMWOp, bytes: i32, offset: i32, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: Type): BinaryenExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenAtomicRMW(this.ref, op, bytes, offset, ptr, value, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAtomicCmpxchg(bytes: i32, offset: i32, ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, replacement: BinaryenExpressionRef, type: Type): BinaryenExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenAtomicCmpxchg(this.ref, bytes, offset, ptr, expected, replacement, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAtomicWait(ptr: BinaryenExpressionRef, expected: BinaryenExpressionRef, timeout: BinaryenExpressionRef, expectedType: BinaryenType): BinaryenExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenAtomicWait(this.ref, ptr, expected, timeout, expectedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAtomicWake(ptr: BinaryenExpressionRef, wakeCount: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||||
|
if (this.noEmit) return 0;
|
||||||
|
return _BinaryenAtomicWake(this.ref, ptr, wakeCount);
|
||||||
|
}
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
|
|
||||||
createSetLocal(index: i32, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
createSetLocal(index: i32, value: BinaryenExpressionRef): BinaryenExpressionRef {
|
||||||
@ -323,8 +374,8 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenBlock(this.ref, cStr, cArr, children.length, type);
|
return _BinaryenBlock(this.ref, cStr, cArr, children.length, type);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr);
|
|
||||||
_free(cArr);
|
_free(cArr);
|
||||||
|
_free(cStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,9 +434,9 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenSwitch(this.ref, cArr, k, cStr, condition, value);
|
return _BinaryenSwitch(this.ref, cArr, k, cStr, condition, value);
|
||||||
} finally {
|
} finally {
|
||||||
for (i = 0; i < k; ++i) _free(strs[i]);
|
|
||||||
_free(cArr);
|
|
||||||
_free(cStr);
|
_free(cStr);
|
||||||
|
_free(cArr);
|
||||||
|
for (i = k - 1; i >= 0; --i) _free(strs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +467,7 @@ export class Module {
|
|||||||
|
|
||||||
// meta
|
// meta
|
||||||
|
|
||||||
addGlobal(name: string, type: Type, mutable: bool, initializer: BinaryenExpressionRef): BinaryenImportRef {
|
addGlobal(name: string, type: Type, mutable: bool, initializer: BinaryenExpressionRef): BinaryenGlobalRef {
|
||||||
if (this.noEmit) return 0;
|
if (this.noEmit) return 0;
|
||||||
const cStr: CString = allocString(name);
|
const cStr: CString = allocString(name);
|
||||||
try {
|
try {
|
||||||
@ -433,8 +484,8 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenAddFunction(this.ref, cStr, type, cArr, varTypes.length, body);
|
return _BinaryenAddFunction(this.ref, cStr, type, cArr, varTypes.length, body);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr);
|
|
||||||
_free(cArr);
|
_free(cArr);
|
||||||
|
_free(cStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,8 +496,8 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenAddExport(this.ref, cStr1, cStr2);
|
return _BinaryenAddExport(this.ref, cStr1, cStr2);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr1);
|
|
||||||
_free(cStr2);
|
_free(cStr2);
|
||||||
|
_free(cStr1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,9 +519,9 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
return _BinaryenAddImport(this.ref, cStr1, cStr2, cStr3, type);
|
return _BinaryenAddImport(this.ref, cStr1, cStr2, cStr3, type);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr1);
|
|
||||||
_free(cStr2);
|
|
||||||
_free(cStr3);
|
_free(cStr3);
|
||||||
|
_free(cStr2);
|
||||||
|
_free(cStr1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,11 +557,11 @@ export class Module {
|
|||||||
try {
|
try {
|
||||||
_BinaryenSetMemory(this.ref, initial, maximum, cStr, cArr1, cArr2, cArr3, k);
|
_BinaryenSetMemory(this.ref, initial, maximum, cStr, cArr1, cArr2, cArr3, k);
|
||||||
} finally {
|
} finally {
|
||||||
_free(cStr);
|
|
||||||
for (i = 0; i < k; ++i) _free(segs[i]);
|
|
||||||
_free(cArr1);
|
|
||||||
_free(cArr2);
|
|
||||||
_free(cArr3);
|
_free(cArr3);
|
||||||
|
_free(cArr2);
|
||||||
|
_free(cArr1);
|
||||||
|
for (i = k - 1; i >= 0; --i) _free(segs[i]);
|
||||||
|
_free(cStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,6 +591,45 @@ export class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getExpressionId(expr: BinaryenExpressionRef): ExpressionId {
|
||||||
|
return _BinaryenExpressionGetId(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getExpressionType(expr: BinaryenExpressionRef): Type {
|
||||||
|
return _BinaryenExpressionGetType(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function printExpression(expr: BinaryenExpressionRef): void {
|
||||||
|
return _BinaryenExpressionPrint(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConstValueI32(expr: BinaryenExpressionRef): i32 {
|
||||||
|
return _BinaryenConstGetValueI32(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConstValueI64Low(expr: BinaryenExpressionRef): i32 {
|
||||||
|
return _BinaryenConstGetValueI64Low(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConstValueI64High(expr: BinaryenExpressionRef): i32 {
|
||||||
|
return _BinaryenConstGetValueI64High(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConstValueI64(expr: BinaryenExpressionRef): I64 {
|
||||||
|
return new I64(
|
||||||
|
_BinaryenConstGetValueI64Low(expr),
|
||||||
|
_BinaryenConstGetValueI64High(expr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConstValueF32(expr: BinaryenExpressionRef): f32 {
|
||||||
|
return _BinaryenConstGetValueF32(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConstValueF64(expr: BinaryenExpressionRef): f64 {
|
||||||
|
return _BinaryenConstGetValueF64(expr);
|
||||||
|
}
|
||||||
|
|
||||||
export class Relooper {
|
export class Relooper {
|
||||||
|
|
||||||
module: Module;
|
module: Module;
|
||||||
@ -596,7 +686,7 @@ export class Relooper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
// TODO: investigate stack allocation?
|
// can't do stack allocation here: STACKTOP is a global in WASM but a hidden variable in asm.js
|
||||||
|
|
||||||
function allocU8Array(u8s: Uint8Array | null): CArray<u8> {
|
function allocU8Array(u8s: Uint8Array | null): CArray<u8> {
|
||||||
if (!u8s) return 0;
|
if (!u8s) return 0;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Module, MemorySegment, UnaryOp, BinaryOp, HostOp, Type as BinaryenType, Relooper } from "./binaryen";
|
import { Module, MemorySegment, UnaryOp, BinaryOp, HostOp, Type as BinaryenType, Relooper } from "./binaryen";
|
||||||
import { PATH_DELIMITER } from "./constants";
|
import { PATH_DELIMITER } from "./constants";
|
||||||
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
|
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
|
||||||
import { Program, ClassTemplate, Element, ElementKind, Enum, FunctionTemplate, FunctionInstance, Global, Local, Namespace, Parameter } from "./program";
|
import { Program, ClassPrototype, Element, ElementKind, Enum, FunctionPrototype, Function, Global, Local, Namespace, Parameter } from "./program";
|
||||||
import { CharCode, I64, U64, normalizePath, sb } from "./util";
|
import { CharCode, I64, U64, normalizePath, sb } from "./util";
|
||||||
import { Token } from "./tokenizer";
|
import { Token } from "./tokenizer";
|
||||||
import {
|
import {
|
||||||
@ -96,11 +96,11 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
options: Options;
|
options: Options;
|
||||||
module: Module;
|
module: Module;
|
||||||
|
|
||||||
startFunction: FunctionInstance;
|
startFunction: Function;
|
||||||
startFunctionBody: BinaryenExpressionRef[] = new Array();
|
startFunctionBody: BinaryenExpressionRef[] = new Array();
|
||||||
|
|
||||||
currentType: Type = Type.void;
|
currentType: Type = Type.void;
|
||||||
currentFunction: FunctionInstance;
|
currentFunction: Function;
|
||||||
disallowContinue: bool = true;
|
disallowContinue: bool = true;
|
||||||
|
|
||||||
memoryOffset: U64 = new U64(8, 0); // leave space for (any size of) NULL
|
memoryOffset: U64 = new U64(8, 0); // leave space for (any size of) NULL
|
||||||
@ -118,8 +118,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
this.program = program;
|
this.program = program;
|
||||||
this.options = options ? options : new Options();
|
this.options = options ? options : new Options();
|
||||||
this.module = this.options.noEmit ? Module.createStub() : Module.create();
|
this.module = this.options.noEmit ? Module.createStub() : Module.create();
|
||||||
const startFunctionTemplate: FunctionTemplate = new FunctionTemplate(program, "start", null);
|
const startFunctionTemplate: FunctionPrototype = new FunctionPrototype(program, "start", null);
|
||||||
const startFunctionInstance: FunctionInstance = new FunctionInstance(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
|
const startFunctionInstance: Function = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
|
||||||
this.currentFunction = this.startFunction = startFunctionInstance;
|
this.currentFunction = this.startFunction = startFunctionInstance;
|
||||||
this.memoryOffset = new U64(2 * (this.options.target == Target.WASM64 ? 8 : 4), 0); // leave space for `null` and heapStart (both of usize type)
|
this.memoryOffset = new U64(2 * (this.options.target == Target.WASM64 ? 8 : 4), 0); // leave space for `null` and heapStart (both of usize type)
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// otherwise a top-level statement that is part of the start function's body
|
// otherwise a top-level statement that is part of the start function's body
|
||||||
default: {
|
default: {
|
||||||
const previousFunction: FunctionInstance = this.currentFunction;
|
const previousFunction: Function = this.currentFunction;
|
||||||
this.currentFunction = this.startFunction;
|
this.currentFunction = this.startFunction;
|
||||||
this.startFunctionBody.push(this.compileStatement(statement));
|
this.startFunctionBody.push(this.compileStatement(statement));
|
||||||
this.currentFunction = previousFunction;
|
this.currentFunction = previousFunction;
|
||||||
@ -290,7 +290,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let initializeInStart: bool;
|
let initializeInStart: bool;
|
||||||
if (element.hasConstantValue) {
|
if (element.hasConstantValue) {
|
||||||
if (type.isLongInteger)
|
if (type.isLongInteger)
|
||||||
initializer = this.module.createI64(element.constantIntegerValue.lo, element.constantIntegerValue.hi);
|
initializer = element.constantIntegerValue ? this.module.createI64(element.constantIntegerValue.lo, element.constantIntegerValue.hi) : this.module.createI64(0, 0);
|
||||||
else if (type.kind == TypeKind.F32)
|
else if (type.kind == TypeKind.F32)
|
||||||
initializer = this.module.createF32(element.constantFloatValue);
|
initializer = this.module.createF32(element.constantFloatValue);
|
||||||
else if (type.kind == TypeKind.F64)
|
else if (type.kind == TypeKind.F64)
|
||||||
@ -298,11 +298,11 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
else if (type.isSmallInteger) {
|
else if (type.isSmallInteger) {
|
||||||
if (type.isSignedInteger) {
|
if (type.isSignedInteger) {
|
||||||
const shift: i32 = type.smallIntegerShift;
|
const shift: i32 = type.smallIntegerShift;
|
||||||
initializer = this.module.createI32(element.constantIntegerValue.toI32() << shift >> shift);
|
initializer = this.module.createI32(element.constantIntegerValue ? element.constantIntegerValue.toI32() << shift >> shift : 0);
|
||||||
} else
|
} else
|
||||||
initializer = this.module.createI32(element.constantIntegerValue.toI32() & type.smallIntegerMask);
|
initializer = this.module.createI32(element.constantIntegerValue ? element.constantIntegerValue.toI32() & type.smallIntegerMask: 0);
|
||||||
} else
|
} else
|
||||||
initializer = this.module.createI32(element.constantIntegerValue.toI32());
|
initializer = this.module.createI32(element.constantIntegerValue ? element.constantIntegerValue.toI32() : 0);
|
||||||
initializeInStart = false;
|
initializeInStart = false;
|
||||||
this.module.addGlobal(element.internalName, binaryenType, element.isMutable, initializer);
|
this.module.addGlobal(element.internalName, binaryenType, element.isMutable, initializer);
|
||||||
} else if (declaration) {
|
} else if (declaration) {
|
||||||
@ -374,16 +374,16 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
compileFunctionDeclaration(declaration: FunctionDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): void {
|
compileFunctionDeclaration(declaration: FunctionDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const element: Element | null = <Element | null>this.program.elements.get(internalName);
|
const element: Element | null = <Element | null>this.program.elements.get(internalName);
|
||||||
if (!element || element.kind != ElementKind.FUNCTION)
|
if (!element || element.kind != ElementKind.FUNCTION_PROTOTYPE)
|
||||||
throw new Error("unexpected missing function");
|
throw new Error("unexpected missing function");
|
||||||
const resolvedTypeArguments: Type[] | null = this.program.resolveTypeArguments(declaration.typeParameters, typeArguments, contextualTypeArguments, alternativeReportNode); // reports
|
const resolvedTypeArguments: Type[] | null = this.program.resolveTypeArguments(declaration.typeParameters, typeArguments, contextualTypeArguments, alternativeReportNode); // reports
|
||||||
if (!resolvedTypeArguments)
|
if (!resolvedTypeArguments)
|
||||||
return;
|
return;
|
||||||
this.compileFunction(<FunctionTemplate>element, resolvedTypeArguments, contextualTypeArguments);
|
this.compileFunction(<FunctionPrototype>element, resolvedTypeArguments, contextualTypeArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileFunction(template: FunctionTemplate, typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null = null): void {
|
compileFunction(template: FunctionPrototype, typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null = null): void {
|
||||||
const instance: FunctionInstance | null = template.instantiate(typeArguments, contextualTypeArguments);
|
const instance: Function | null = template.resolve(typeArguments, contextualTypeArguments);
|
||||||
if (!instance || instance.compiled)
|
if (!instance || instance.compiled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
instance.compiled = true;
|
instance.compiled = true;
|
||||||
|
|
||||||
// compile statements
|
// compile statements
|
||||||
const previousFunction: FunctionInstance = this.currentFunction;
|
const previousFunction: Function = this.currentFunction;
|
||||||
this.currentFunction = instance;
|
this.currentFunction = instance;
|
||||||
const stmts: BinaryenExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
|
const stmts: BinaryenExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
|
||||||
this.currentFunction = previousFunction;
|
this.currentFunction = previousFunction;
|
||||||
@ -468,18 +468,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
for (let [name, element] of ns.members) {
|
for (let [name, element] of ns.members) {
|
||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
|
|
||||||
case ElementKind.CLASS:
|
case ElementKind.CLASS_PROTOTYPE:
|
||||||
if ((noTreeShaking || (<ClassTemplate>element).isExport) && !(<ClassTemplate>element).isGeneric)
|
if ((noTreeShaking || (<ClassPrototype>element).isExport) && !(<ClassPrototype>element).isGeneric)
|
||||||
this.compileClass(<ClassTemplate>element, []);
|
this.compileClass(<ClassPrototype>element, []);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.ENUM:
|
case ElementKind.ENUM:
|
||||||
this.compileEnum(<Enum>element);
|
this.compileEnum(<Enum>element);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.FUNCTION:
|
case ElementKind.FUNCTION_PROTOTYPE:
|
||||||
if ((noTreeShaking || (<FunctionTemplate>element).isExport) && !(<FunctionTemplate>element).isGeneric)
|
if ((noTreeShaking || (<FunctionPrototype>element).isExport) && !(<FunctionPrototype>element).isGeneric)
|
||||||
this.compileFunction(<FunctionTemplate>element, []);
|
this.compileFunction(<FunctionPrototype>element, []);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.GLOBAL:
|
case ElementKind.GLOBAL:
|
||||||
@ -506,18 +506,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
throw new Error("unexpected missing element");
|
throw new Error("unexpected missing element");
|
||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
|
|
||||||
case ElementKind.CLASS:
|
case ElementKind.CLASS_PROTOTYPE:
|
||||||
if (!(<ClassTemplate>element).isGeneric)
|
if (!(<ClassPrototype>element).isGeneric)
|
||||||
this.compileClass(<ClassTemplate>element, []);
|
this.compileClass(<ClassPrototype>element, []);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.ENUM:
|
case ElementKind.ENUM:
|
||||||
this.compileEnum(<Enum>element);
|
this.compileEnum(<Enum>element);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.FUNCTION:
|
case ElementKind.FUNCTION_PROTOTYPE:
|
||||||
if (!(<FunctionTemplate>element).isGeneric)
|
if (!(<FunctionPrototype>element).isGeneric)
|
||||||
this.compileFunction(<FunctionTemplate>element, []);
|
this.compileFunction(<FunctionPrototype>element, []);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.GLOBAL:
|
case ElementKind.GLOBAL:
|
||||||
@ -536,15 +536,15 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
compileClassDeclaration(declaration: ClassDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): void {
|
compileClassDeclaration(declaration: ClassDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const element: Element | null = <Element | null>this.program.elements.get(internalName);
|
const element: Element | null = <Element | null>this.program.elements.get(internalName);
|
||||||
if (!element || element.kind != ElementKind.CLASS)
|
if (!element || element.kind != ElementKind.CLASS_PROTOTYPE)
|
||||||
throw new Error("unexpected missing class");
|
throw new Error("unexpected missing class");
|
||||||
const resolvedTypeArguments: Type[] | null = this.program.resolveTypeArguments(declaration.typeParameters, typeArguments, contextualTypeArguments, alternativeReportNode); // reports
|
const resolvedTypeArguments: Type[] | null = this.program.resolveTypeArguments(declaration.typeParameters, typeArguments, contextualTypeArguments, alternativeReportNode); // reports
|
||||||
if (!resolvedTypeArguments)
|
if (!resolvedTypeArguments)
|
||||||
return;
|
return;
|
||||||
this.compileClass(<ClassTemplate>element, resolvedTypeArguments, contextualTypeArguments);
|
this.compileClass(<ClassPrototype>element, resolvedTypeArguments, contextualTypeArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileClass(cls: ClassTemplate, typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null = null) {
|
compileClass(cls: ClassPrototype, typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null = null) {
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,9 +1053,9 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): BinaryenExpressionRef {
|
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): BinaryenExpressionRef {
|
||||||
const toType: Type | null = this.program.resolveType(expression.toType, this.currentFunction.contextualTypeArguments, true); // reports
|
const toType: Type | null = this.program.resolveType(expression.toType, this.currentFunction.contextualTypeArguments); // reports
|
||||||
if (toType && toType != contextualType) {
|
if (toType && toType != contextualType) {
|
||||||
const expr: BinaryenExpressionRef = this.compileExpression(expression.expression, <Type>toType);
|
const expr: BinaryenExpressionRef = this.compileExpression(expression.expression, <Type>toType, false);
|
||||||
return this.convertExpression(expr, this.currentType, <Type>toType);
|
return this.convertExpression(expr, this.currentType, <Type>toType);
|
||||||
}
|
}
|
||||||
return this.compileExpression(expression.expression, contextualType);
|
return this.compileExpression(expression.expression, contextualType);
|
||||||
@ -1316,9 +1316,13 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileCallExpression(expression: CallExpression, contextualType: Type): BinaryenExpressionRef {
|
compileCallExpression(expression: CallExpression, contextualType: Type): BinaryenExpressionRef {
|
||||||
const element: Element | null = this.program.resolveElement(expression, this.currentFunction);
|
const element: Element | null = this.program.resolveElement(expression.expression, this.currentFunction); // reports
|
||||||
if (!element || element.kind != ElementKind.FUNCTION)
|
if (!element)
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
|
if (element.kind != ElementKind.FUNCTION_PROTOTYPE) {
|
||||||
|
// TODO: report 'Cannot invoke an expression whose type lacks a call signature.'
|
||||||
|
return this.module.createUnreachable();
|
||||||
|
}
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1401,7 +1405,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
// throw new Error("not implemented");
|
// throw new Error("not implemented");
|
||||||
|
|
||||||
// getter
|
// getter
|
||||||
if (element.kind == ElementKind.FUNCTION && (<FunctionTemplate>element).isGetter)
|
if (element.kind == ElementKind.FUNCTION_PROTOTYPE && (<FunctionPrototype>element).isGetter)
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
|
|
||||||
this.error(DiagnosticCode.Operation_not_supported, expression.range);
|
this.error(DiagnosticCode.Operation_not_supported, expression.range);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
export const PATH_DELIMITER: string = "/";
|
export const PATH_DELIMITER: string = "/";
|
||||||
export const PARENT_SUBST: string = "..";
|
export const PARENT_SUBST: string = "..";
|
||||||
export const GETTER_PREFIX: string = "get:";
|
export const GETTER_PREFIX: string = "get ";
|
||||||
export const SETTER_PREFIX: string = "set:";
|
export const SETTER_PREFIX: string = "set ";
|
||||||
export const INSTANCE_DELIMITER: string = "#";
|
export const INSTANCE_DELIMITER: string = "#";
|
||||||
export const STATIC_DELIMITER: string = ".";
|
export const STATIC_DELIMITER: string = ".";
|
||||||
|
@ -51,10 +51,12 @@ export enum DiagnosticCode {
|
|||||||
Type_0_is_not_generic = 2315,
|
Type_0_is_not_generic = 2315,
|
||||||
Type_0_is_not_assignable_to_type_1 = 2322,
|
Type_0_is_not_assignable_to_type_1 = 2322,
|
||||||
_this_cannot_be_referenced_in_current_location = 2332,
|
_this_cannot_be_referenced_in_current_location = 2332,
|
||||||
|
Property_0_does_not_exist_on_type_1 = 2339,
|
||||||
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357,
|
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357,
|
||||||
The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access = 2364,
|
The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access = 2364,
|
||||||
Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391,
|
Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391,
|
||||||
Duplicate_function_implementation = 2393,
|
Duplicate_function_implementation = 2393,
|
||||||
|
Export_declaration_conflicts_with_exported_declaration_of_0 = 2484,
|
||||||
The_target_of_an_assignment_must_be_a_variable_or_a_property_access = 2541,
|
The_target_of_an_assignment_must_be_a_variable_or_a_property_access = 2541,
|
||||||
Expected_0_type_arguments_but_got_1 = 2558,
|
Expected_0_type_arguments_but_got_1 = 2558,
|
||||||
File_0_not_found = 6054
|
File_0_not_found = 6054
|
||||||
@ -112,10 +114,12 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
|||||||
case 2315: return "Type '{0}' is not generic.";
|
case 2315: return "Type '{0}' is not generic.";
|
||||||
case 2322: return "Type '{0}' is not assignable to type '{1}'.";
|
case 2322: return "Type '{0}' is not assignable to type '{1}'.";
|
||||||
case 2332: return "'this' cannot be referenced in current location.";
|
case 2332: return "'this' cannot be referenced in current location.";
|
||||||
|
case 2339: return "Property '{0}' does not exist on type '{1}'.";
|
||||||
case 2357: return "The operand of an increment or decrement operator must be a variable or a property access.";
|
case 2357: return "The operand of an increment or decrement operator must be a variable or a property access.";
|
||||||
case 2364: return "The left-hand side of an assignment expression must be a variable or a property access.";
|
case 2364: return "The left-hand side of an assignment expression must be a variable or a property access.";
|
||||||
case 2391: return "Function implementation is missing or not immediately following the declaration.";
|
case 2391: return "Function implementation is missing or not immediately following the declaration.";
|
||||||
case 2393: return "Duplicate function implementation.";
|
case 2393: return "Duplicate function implementation.";
|
||||||
|
case 2484: return "Export declaration conflicts with exported declaration of '{0}'.";
|
||||||
case 2541: return "The target of an assignment must be a variable or a property access.";
|
case 2541: return "The target of an assignment must be a variable or a property access.";
|
||||||
case 2558: return "Expected {0} type arguments, but got {1}.";
|
case 2558: return "Expected {0} type arguments, but got {1}.";
|
||||||
case 6054: return "File '{0}' not found.";
|
case 6054: return "File '{0}' not found.";
|
||||||
|
@ -51,10 +51,12 @@
|
|||||||
"Type '{0}' is not generic.": 2315,
|
"Type '{0}' is not generic.": 2315,
|
||||||
"Type '{0}' is not assignable to type '{1}'.": 2322,
|
"Type '{0}' is not assignable to type '{1}'.": 2322,
|
||||||
"'this' cannot be referenced in current location.": 2332,
|
"'this' cannot be referenced in current location.": 2332,
|
||||||
|
"Property '{0}' does not exist on type '{1}'.": 2339,
|
||||||
"The operand of an increment or decrement operator must be a variable or a property access.": 2357,
|
"The operand of an increment or decrement operator must be a variable or a property access.": 2357,
|
||||||
"The left-hand side of an assignment expression must be a variable or a property access.": 2364,
|
"The left-hand side of an assignment expression must be a variable or a property access.": 2364,
|
||||||
"Function implementation is missing or not immediately following the declaration.": 2391,
|
"Function implementation is missing or not immediately following the declaration.": 2391,
|
||||||
"Duplicate function implementation.": 2393,
|
"Duplicate function implementation.": 2393,
|
||||||
|
"Export declaration conflicts with exported declaration of '{0}'.": 2484,
|
||||||
"The target of an assignment must be a variable or a property access.": 2541,
|
"The target of an assignment must be a variable or a property access.": 2541,
|
||||||
"Expected {0} type arguments, but got {1}.": 2558,
|
"Expected {0} type arguments, but got {1}.": 2558,
|
||||||
|
|
||||||
|
@ -11,10 +11,12 @@ export enum DiagnosticCategory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function diagnosticCategoryToString(category: DiagnosticCategory): string {
|
export function diagnosticCategoryToString(category: DiagnosticCategory): string {
|
||||||
if (category == DiagnosticCategory.INFO) return "INFO";
|
switch (category) {
|
||||||
if (category == DiagnosticCategory.WARNING) return "WARNING";
|
case DiagnosticCategory.INFO: return "INFO";
|
||||||
if (category == DiagnosticCategory.ERROR) return "ERROR";
|
case DiagnosticCategory.WARNING: return "WARNING";
|
||||||
return "";
|
case DiagnosticCategory.ERROR: return "ERROR";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorBlue: string = "\u001b[93m";
|
const colorBlue: string = "\u001b[93m";
|
||||||
@ -23,10 +25,12 @@ const colorRed: string = "\u001b[91m";
|
|||||||
const colorReset: string = "\u001b[0m";
|
const colorReset: string = "\u001b[0m";
|
||||||
|
|
||||||
export function diagnosticCategoryToColor(category: DiagnosticCategory): string {
|
export function diagnosticCategoryToColor(category: DiagnosticCategory): string {
|
||||||
if (category == DiagnosticCategory.INFO) return colorBlue;
|
switch (category) {
|
||||||
if (category == DiagnosticCategory.WARNING) return colorYellow;
|
case DiagnosticCategory.INFO: return colorBlue;
|
||||||
if (category == DiagnosticCategory.ERROR) return colorRed;
|
case DiagnosticCategory.WARNING: return colorYellow;
|
||||||
return "";
|
case DiagnosticCategory.ERROR: return colorRed;
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DiagnosticMessage {
|
export class DiagnosticMessage {
|
||||||
|
68
src/evaluator.ts
Normal file
68
src/evaluator.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// TODO: not yet decided whether we'll need this
|
||||||
|
// https://github.com/WebAssembly/binaryen/pull/1294
|
||||||
|
// https://github.com/WebAssembly/binaryen/pull/1295
|
||||||
|
|
||||||
|
import { Type } from "./types";
|
||||||
|
import { I64 } from "./util";
|
||||||
|
import {
|
||||||
|
|
||||||
|
NodeKind,
|
||||||
|
|
||||||
|
Expression,
|
||||||
|
BinaryExpression,
|
||||||
|
LiteralExpression,
|
||||||
|
UnaryExpression,
|
||||||
|
UnaryPostfixExpression,
|
||||||
|
UnaryPrefixExpression
|
||||||
|
|
||||||
|
} from "./ast";
|
||||||
|
|
||||||
|
export class Evaluator {
|
||||||
|
|
||||||
|
success: bool = false;
|
||||||
|
type: Type;
|
||||||
|
integerValue: I64;
|
||||||
|
floatValue: f64;
|
||||||
|
stringValue: string;
|
||||||
|
|
||||||
|
constructor(initialType: Type) {
|
||||||
|
this.type = initialType;
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate(expression: Expression): this {
|
||||||
|
switch (expression.kind) {
|
||||||
|
|
||||||
|
case NodeKind.BINARY:
|
||||||
|
this.evaluateBinary(<BinaryExpression>expression);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NodeKind.LITERAL:
|
||||||
|
this.evaluateLiteral(<LiteralExpression>expression);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NodeKind.UNARYPREFIX:
|
||||||
|
this.evaluateUnaryPrefix(<UnaryPrefixExpression>expression);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private evaluateBinary(expression: BinaryExpression): this {
|
||||||
|
// TODO
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private evaluateLiteral(expression: LiteralExpression): this {
|
||||||
|
// TODO
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private evaluateUnaryPrefix(expression: UnaryPrefixExpression): this {
|
||||||
|
// TODO
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function evaluate(expression: Expression, contextualType: Type): Evaluator {
|
||||||
|
return new Evaluator(contextualType).evaluate(expression);
|
||||||
|
}
|
463
src/program.ts
463
src/program.ts
@ -201,113 +201,98 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
private initializeClass(declaration: ClassDeclaration): void {
|
private initializeClass(declaration: ClassDeclaration): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const template: ClassTemplate = new ClassTemplate(this, internalName, declaration);
|
if (this.elements.has(internalName)) {
|
||||||
if (this.elements.has(internalName))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.elements.set(internalName, template);
|
}
|
||||||
|
const prototype: ClassPrototype = new ClassPrototype(this, internalName, declaration);
|
||||||
|
this.elements.set(internalName, prototype);
|
||||||
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, template);
|
this.exports.set(internalName, prototype);
|
||||||
}
|
}
|
||||||
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
||||||
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
||||||
const memberDeclaration: DeclarationStatement = memberDeclarations[j];
|
const memberDeclaration: DeclarationStatement = memberDeclarations[j];
|
||||||
switch (memberDeclaration.kind) {
|
if (memberDeclaration.kind == NodeKind.FIELD)
|
||||||
|
this.initializeField(<FieldDeclaration>memberDeclaration, prototype);
|
||||||
case NodeKind.FIELD:
|
else if (memberDeclaration.kind == NodeKind.METHOD)
|
||||||
this.initializeField(<FieldDeclaration>memberDeclaration, template);
|
this.initializeMethod(<MethodDeclaration>memberDeclaration, prototype);
|
||||||
break;
|
else
|
||||||
|
throw new Error("unexpected class member");
|
||||||
case NodeKind.METHOD:
|
|
||||||
this.initializeMethod(<MethodDeclaration>memberDeclaration, template);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error("unexpected class member");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeField(declaration: FieldDeclaration, template: ClassTemplate): void {
|
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
||||||
const name: string = declaration.identifier.name;
|
const name: string = declaration.identifier.name;
|
||||||
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
if (classPrototype.members.has(name)) {
|
||||||
const internalName: string = declaration.internalName;
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
if (template.members.has(name))
|
return;
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
}
|
||||||
else {
|
const internalName: string = declaration.internalName;
|
||||||
const global: Global = new Global(this, internalName, declaration, null);
|
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) { // static fields become globals
|
||||||
template.members.set(name, global);
|
const global: Global = new Global(this, internalName, declaration, null);
|
||||||
}
|
classPrototype.members.set(name, global);
|
||||||
} else {
|
} else {
|
||||||
if (template.fieldDeclarations.has(name))
|
const field: FieldPrototype = new FieldPrototype(classPrototype, internalName, declaration);
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, name);
|
classPrototype.members.set(name, field);
|
||||||
else
|
|
||||||
template.fieldDeclarations.set(name, declaration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeMethod(declaration: MethodDeclaration, template: ClassTemplate): void {
|
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
||||||
let name: string = declaration.identifier.name;
|
let name: string = declaration.identifier.name;
|
||||||
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
const internalName: string = declaration.internalName;
|
||||||
const internalName: string = declaration.internalName;
|
if (classPrototype.members.has(name)) {
|
||||||
if (template.members.has(name))
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
return;
|
||||||
else {
|
|
||||||
const func: FunctionTemplate = new FunctionTemplate(this, internalName, declaration);
|
|
||||||
let modifiers: Modifier[] | null;
|
|
||||||
if (modifiers = declaration.modifiers) {
|
|
||||||
for (let i: i32 = 0, k: i32 = modifiers.length; i < k; ++i) {
|
|
||||||
const modifier: Modifier = modifiers[i];
|
|
||||||
if (modifier.modifierKind == ModifierKind.GET) {
|
|
||||||
name = GETTER_PREFIX + name;
|
|
||||||
break;
|
|
||||||
} else if (modifier.modifierKind == ModifierKind.SET) {
|
|
||||||
name = SETTER_PREFIX + name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template.members.set(name, func);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (template.methodDeclarations.has(name))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, name);
|
|
||||||
else
|
|
||||||
template.methodDeclarations.set(name, declaration);
|
|
||||||
}
|
}
|
||||||
|
const func: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, hasModifier(ModifierKind.STATIC, declaration.modifiers) ? null : classPrototype);
|
||||||
|
let modifiers: Modifier[] | null;
|
||||||
|
if (modifiers = declaration.modifiers) {
|
||||||
|
for (let i: i32 = 0, k: i32 = modifiers.length; i < k; ++i) {
|
||||||
|
const modifier: Modifier = modifiers[i];
|
||||||
|
if (modifier.modifierKind == ModifierKind.GET) {
|
||||||
|
name = GETTER_PREFIX + name;
|
||||||
|
break;
|
||||||
|
} else if (modifier.modifierKind == ModifierKind.SET) {
|
||||||
|
name = SETTER_PREFIX + name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classPrototype.members.set(name, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeEnum(declaration: EnumDeclaration): void {
|
private initializeEnum(declaration: EnumDeclaration): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const enm: Enum = new Enum(this, internalName, declaration);
|
if (this.elements.has(internalName)) {
|
||||||
if (this.elements.has(internalName))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
return;
|
||||||
this.elements.set(internalName, enm);
|
|
||||||
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
|
||||||
if (this.exports.has(internalName))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
|
||||||
else
|
|
||||||
this.exports.set(internalName, enm);
|
|
||||||
}
|
|
||||||
const members: EnumValueDeclaration[] = declaration.members;
|
|
||||||
for (let i: i32 = 0, k: i32 = members.length; i < k; ++i)
|
|
||||||
this.initializeEnumValue(members[i], enm);
|
|
||||||
}
|
}
|
||||||
|
const enm: Enum = new Enum(this, internalName, declaration);
|
||||||
|
this.elements.set(internalName, enm);
|
||||||
|
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
||||||
|
if (this.exports.has(internalName))
|
||||||
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
|
else
|
||||||
|
this.exports.set(internalName, enm);
|
||||||
|
}
|
||||||
|
const values: EnumValueDeclaration[] = declaration.members;
|
||||||
|
for (let i: i32 = 0, k: i32 = values.length; i < k; ++i)
|
||||||
|
this.initializeEnumValue(values[i], enm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeEnumValue(declaration: EnumValueDeclaration, enm: Enum): void {
|
private initializeEnumValue(declaration: EnumValueDeclaration, enm: Enum): void {
|
||||||
const name: string = declaration.identifier.name;
|
const name: string = declaration.identifier.name;
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (enm.members.has(name))
|
if (enm.members.has(name)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
return;
|
||||||
const value: EnumValue = new EnumValue(enm, this, internalName, declaration);
|
|
||||||
enm.members.set(name, value);
|
|
||||||
}
|
}
|
||||||
|
const value: EnumValue = new EnumValue(enm, this, internalName, declaration);
|
||||||
|
enm.members.set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeExports(statement: ExportStatement, queuedExports: Map<string,QueuedExport>): void {
|
private initializeExports(statement: ExportStatement, queuedExports: Map<string,QueuedExport>): void {
|
||||||
@ -318,35 +303,35 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
private initializeExport(member: ExportMember, internalPath: string | null, queuedExports: Map<string,QueuedExport>): void {
|
private initializeExport(member: ExportMember, internalPath: string | null, queuedExports: Map<string,QueuedExport>): void {
|
||||||
const exportName: string = member.range.source.internalPath + PATH_DELIMITER + member.externalIdentifier.name;
|
const exportName: string = member.range.source.internalPath + PATH_DELIMITER + member.externalIdentifier.name;
|
||||||
if (queuedExports.has(exportName))
|
if (queuedExports.has(exportName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, member.externalIdentifier.range, exportName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, member.externalIdentifier.range, exportName);
|
||||||
else {
|
return;
|
||||||
const queuedExport: QueuedExport = new QueuedExport();
|
|
||||||
if (internalPath == null) {
|
|
||||||
queuedExport.isForeign = false;
|
|
||||||
queuedExport.referencedName = member.range.source.internalPath + PATH_DELIMITER + member.identifier.name;
|
|
||||||
} else {
|
|
||||||
queuedExport.isForeign = true;
|
|
||||||
queuedExport.referencedName = (<string>internalPath) + PATH_DELIMITER + member.identifier.name;
|
|
||||||
}
|
|
||||||
queuedExport.member = member;
|
|
||||||
queuedExports.set(exportName, queuedExport);
|
|
||||||
}
|
}
|
||||||
|
const queuedExport: QueuedExport = new QueuedExport();
|
||||||
|
if (internalPath == null) {
|
||||||
|
queuedExport.isForeign = false;
|
||||||
|
queuedExport.referencedName = member.range.source.internalPath + PATH_DELIMITER + member.identifier.name;
|
||||||
|
} else {
|
||||||
|
queuedExport.isForeign = true;
|
||||||
|
queuedExport.referencedName = (<string>internalPath) + PATH_DELIMITER + member.identifier.name;
|
||||||
|
}
|
||||||
|
queuedExport.member = member;
|
||||||
|
queuedExports.set(exportName, queuedExport);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeFunction(declaration: FunctionDeclaration): void {
|
private initializeFunction(declaration: FunctionDeclaration): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const template: FunctionTemplate = new FunctionTemplate(this, internalName, declaration);
|
const prototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
return;
|
||||||
this.elements.set(internalName, template);
|
}
|
||||||
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
this.elements.set(internalName, prototype);
|
||||||
if (this.exports.has(internalName))
|
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (this.exports.has(internalName))
|
||||||
else
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
this.exports.set(internalName, template);
|
else
|
||||||
}
|
this.exports.set(internalName, prototype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,16 +371,16 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
private initializeInterface(declaration: InterfaceDeclaration): void {
|
private initializeInterface(declaration: InterfaceDeclaration): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const template: InterfaceTemplate = new InterfaceTemplate(this, internalName, declaration);
|
const interfacePrototype: InterfacePrototype = new InterfacePrototype(this, internalName, declaration);
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.elements.set(internalName, template);
|
this.elements.set(internalName, interfacePrototype);
|
||||||
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, template);
|
this.exports.set(internalName, interfacePrototype);
|
||||||
}
|
}
|
||||||
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
||||||
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
||||||
@ -403,11 +388,11 @@ export class Program extends DiagnosticEmitter {
|
|||||||
switch (memberDeclaration.kind) {
|
switch (memberDeclaration.kind) {
|
||||||
|
|
||||||
case NodeKind.FIELD:
|
case NodeKind.FIELD:
|
||||||
this.initializeField(<FieldDeclaration>memberDeclaration, template);
|
this.initializeField(<FieldDeclaration>memberDeclaration, interfacePrototype);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.METHOD:
|
case NodeKind.METHOD:
|
||||||
this.initializeMethod(<MethodDeclaration>memberDeclaration, template);
|
this.initializeMethod(<MethodDeclaration>memberDeclaration, interfacePrototype);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -418,16 +403,16 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
private initializeNamespace(declaration: NamespaceDeclaration): void {
|
private initializeNamespace(declaration: NamespaceDeclaration): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const ns: Namespace = new Namespace(this, internalName, declaration);
|
const namespace: Namespace = new Namespace(this, internalName, declaration);
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
else {
|
||||||
this.elements.set(internalName, ns);
|
this.elements.set(internalName, namespace);
|
||||||
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
if (hasModifier(ModifierKind.EXPORT, declaration.modifiers)) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
this.exports.set(internalName, ns);
|
this.exports.set(internalName, namespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const members: Statement[] = declaration.members;
|
const members: Statement[] = declaration.members;
|
||||||
@ -544,12 +529,12 @@ export class Program extends DiagnosticEmitter {
|
|||||||
return typeArguments;
|
return typeArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveElement(expression: Expression, contextualFunction: FunctionInstance): Element | null {
|
resolveElement(expression: Expression, contextualFunction: Function): Element | null {
|
||||||
|
|
||||||
// this
|
// this
|
||||||
if (expression.kind == NodeKind.THIS) {
|
if (expression.kind == NodeKind.THIS) {
|
||||||
if (contextualFunction.instanceMethodOf)
|
if (contextualFunction.instanceMethodOf)
|
||||||
return contextualFunction.instanceMethodOf.template;
|
return contextualFunction.instanceMethodOf;
|
||||||
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -566,22 +551,31 @@ export class Program extends DiagnosticEmitter {
|
|||||||
const programGlobalElement: Element | null = <Element | null>this.elements.get(name);
|
const programGlobalElement: Element | null = <Element | null>this.elements.get(name);
|
||||||
if (programGlobalElement)
|
if (programGlobalElement)
|
||||||
return programGlobalElement;
|
return programGlobalElement;
|
||||||
|
this.error(DiagnosticCode.Cannot_find_name_0, expression.range, name);
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// static or instance property (incl. enum values) or method
|
// static or instance property (incl. enum values) or method
|
||||||
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
} else if (expression.kind == NodeKind.PROPERTYACCESS) {
|
||||||
const target: Element | null = this.resolveElement((<PropertyAccessExpression>expression).expression, contextualFunction);
|
const target: Element | null = this.resolveElement((<PropertyAccessExpression>expression).expression, contextualFunction); // reports
|
||||||
|
let member: Element | null = null;
|
||||||
if (!target)
|
if (!target)
|
||||||
return null;
|
return null;
|
||||||
switch (target.kind) {
|
const propertyName: string = (<PropertyAccessExpression>expression).property.name;
|
||||||
case ElementKind.CLASS:
|
if (target.kind == ElementKind.ENUM)
|
||||||
case ElementKind.ENUM:
|
member = <EnumValue | null>(<Enum>target).members.get(propertyName);
|
||||||
case ElementKind.NAMESPACE:
|
else if (target.kind == ElementKind.CLASS_PROTOTYPE)
|
||||||
}
|
member = <Element | null>(<ClassPrototype>target).members.get(propertyName);
|
||||||
// TODO
|
else if (target.kind == ElementKind.CLASS)
|
||||||
|
member = <Element | null>(<Class>target).members.get(propertyName);
|
||||||
|
else if (target.kind == ElementKind.NAMESPACE)
|
||||||
|
member = <Element | null>(<Namespace>target).members.get(propertyName);
|
||||||
|
if (member)
|
||||||
|
return member;
|
||||||
|
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, expression.range, (<PropertyAccessExpression>expression).property.name, target.internalName);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
throw new Error("not implemented: " + expression.kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,25 +597,29 @@ function checkGlobalDecorator(decorators: DecoratorStatement[]): string | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum ElementKind {
|
export enum ElementKind {
|
||||||
|
CLASS_PROTOTYPE,
|
||||||
CLASS,
|
CLASS,
|
||||||
CLASSINSTANCE,
|
|
||||||
ENUM,
|
ENUM,
|
||||||
ENUMVALUE,
|
ENUMVALUE,
|
||||||
|
FIELD_PROTOTYPE,
|
||||||
|
FIELD,
|
||||||
|
FUNCTION_PROTOTYPE,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
FUNCTIONINSTANCE,
|
|
||||||
GLOBAL,
|
GLOBAL,
|
||||||
|
INTERFACE_PROTOTYPE,
|
||||||
INTERFACE,
|
INTERFACE,
|
||||||
INTERFACEINSTANCE,
|
|
||||||
LOCAL,
|
LOCAL,
|
||||||
NAMESPACE
|
NAMESPACE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Base class of all program elements. */
|
||||||
export abstract class Element {
|
export abstract class Element {
|
||||||
|
|
||||||
kind: ElementKind;
|
kind: ElementKind;
|
||||||
program: Program;
|
program: Program;
|
||||||
internalName: string;
|
internalName: string;
|
||||||
globalExportName: string | null = null;
|
globalExportName: string | null = null;
|
||||||
|
compiled: bool = false;
|
||||||
|
|
||||||
constructor(program: Program, internalName: string) {
|
constructor(program: Program, internalName: string) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
@ -629,59 +627,7 @@ export abstract class Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Enum extends Element {
|
/** A namespace. Also the base class of other namespace-like program elements. */
|
||||||
|
|
||||||
kind = ElementKind.ENUM;
|
|
||||||
declaration: EnumDeclaration | null;
|
|
||||||
members: Map<string,EnumValue> = new Map();
|
|
||||||
compiled: bool = false;
|
|
||||||
|
|
||||||
constructor(program: Program, internalName: string, declaration: EnumDeclaration | null = null) {
|
|
||||||
super(program, internalName);
|
|
||||||
this.declaration = declaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; }
|
|
||||||
get isGlobalExport(): bool { return this.globalExportName != null; }
|
|
||||||
get isConstant(): bool { return this.declaration ? hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are const */ true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EnumValue extends Element {
|
|
||||||
|
|
||||||
kind = ElementKind.ENUMVALUE;
|
|
||||||
declaration: EnumValueDeclaration | null;
|
|
||||||
enum: Enum;
|
|
||||||
hasConstantValue: bool = false;
|
|
||||||
constantValue: i32 = 0;
|
|
||||||
|
|
||||||
constructor(enm: Enum, program: Program, internalName: string, declaration: EnumValueDeclaration | null = null) {
|
|
||||||
super(program, internalName);
|
|
||||||
this.enum = enm;
|
|
||||||
if (!(this.declaration = declaration)) this.hasConstantValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Global extends Element {
|
|
||||||
|
|
||||||
kind = ElementKind.GLOBAL;
|
|
||||||
declaration: VariableLikeDeclarationStatement | null;
|
|
||||||
type: Type | null;
|
|
||||||
hasConstantValue: bool = false;
|
|
||||||
constantIntegerValue: I64 = new I64(0, 0);
|
|
||||||
constantFloatValue: f64 = 0;
|
|
||||||
compiled: bool = false;
|
|
||||||
|
|
||||||
constructor(program: Program, internalName: string, declaration: VariableLikeDeclarationStatement | null, type: Type | null) {
|
|
||||||
super(program, internalName);
|
|
||||||
if (!(this.declaration = declaration)) this.hasConstantValue = true;
|
|
||||||
this.type = type; // resolved later if `null`
|
|
||||||
}
|
|
||||||
|
|
||||||
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; }
|
|
||||||
get isGlobalExport(): bool { return this.globalExportName != null; }
|
|
||||||
get isMutable(): bool { return this.declaration ? hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are immutable */ false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Namespace extends Element {
|
export class Namespace extends Element {
|
||||||
|
|
||||||
kind = ElementKind.NAMESPACE;
|
kind = ElementKind.NAMESPACE;
|
||||||
@ -697,6 +643,61 @@ export class Namespace extends Element {
|
|||||||
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't exports */ false; }
|
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't exports */ false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** An enum. */
|
||||||
|
export class Enum extends Namespace {
|
||||||
|
|
||||||
|
kind = ElementKind.ENUM;
|
||||||
|
declaration: EnumDeclaration | null;
|
||||||
|
members: Map<string,EnumValue> = new Map(); // more specific
|
||||||
|
|
||||||
|
constructor(program: Program, internalName: string, declaration: EnumDeclaration | null = null) {
|
||||||
|
super(program, internalName, null);
|
||||||
|
this.declaration = declaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; }
|
||||||
|
get isGlobalExport(): bool { return this.globalExportName != null; }
|
||||||
|
get isConstant(): bool { return this.declaration ? hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are const */ true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An enum value. */
|
||||||
|
export class EnumValue extends Element {
|
||||||
|
|
||||||
|
kind = ElementKind.ENUMVALUE;
|
||||||
|
declaration: EnumValueDeclaration | null;
|
||||||
|
enum: Enum;
|
||||||
|
hasConstantValue: bool;
|
||||||
|
constantValue: i32 = 0;
|
||||||
|
|
||||||
|
constructor(enm: Enum, program: Program, internalName: string, declaration: EnumValueDeclaration | null = null) {
|
||||||
|
super(program, internalName);
|
||||||
|
this.enum = enm;
|
||||||
|
if (!(this.declaration = declaration)) this.hasConstantValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A global variable. */
|
||||||
|
export class Global extends Element {
|
||||||
|
|
||||||
|
kind = ElementKind.GLOBAL;
|
||||||
|
declaration: VariableLikeDeclarationStatement | null;
|
||||||
|
type: Type | null;
|
||||||
|
hasConstantValue: bool = false;
|
||||||
|
constantIntegerValue: I64 | null = null;
|
||||||
|
constantFloatValue: f64 = 0;
|
||||||
|
|
||||||
|
constructor(program: Program, internalName: string, declaration: VariableLikeDeclarationStatement | null, type: Type | null) {
|
||||||
|
super(program, internalName);
|
||||||
|
if (!(this.declaration = declaration)) this.hasConstantValue = true;
|
||||||
|
this.type = type; // resolved later if `null`, also updates constantKind
|
||||||
|
}
|
||||||
|
|
||||||
|
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; }
|
||||||
|
get isGlobalExport(): bool { return this.globalExportName != null; }
|
||||||
|
get isMutable(): bool { return this.declaration ? hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are immutable */ false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A function parameter. */
|
||||||
export class Parameter {
|
export class Parameter {
|
||||||
|
|
||||||
name: string;
|
name: string;
|
||||||
@ -708,6 +709,7 @@ export class Parameter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A function local. */
|
||||||
export class Local extends Element {
|
export class Local extends Element {
|
||||||
|
|
||||||
kind = ElementKind.LOCAL;
|
kind = ElementKind.LOCAL;
|
||||||
@ -721,28 +723,31 @@ export class Local extends Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FunctionTemplate extends Element {
|
/** A yet unresolved function prototype. */
|
||||||
|
export class FunctionPrototype extends Element {
|
||||||
|
|
||||||
kind = ElementKind.FUNCTION;
|
kind = ElementKind.FUNCTION_PROTOTYPE;
|
||||||
declaration: FunctionDeclaration | null;
|
declaration: FunctionDeclaration | null;
|
||||||
instances: Map<string,FunctionInstance>;
|
classPrototype: ClassPrototype | null;
|
||||||
|
instances: Map<string,Function> = new Map();
|
||||||
isGeneric: bool;
|
isGeneric: bool;
|
||||||
|
|
||||||
constructor(program: Program, internalName: string, declaration: FunctionDeclaration | null) {
|
constructor(program: Program, internalName: string, declaration: FunctionDeclaration | null, classPrototype: ClassPrototype | null = null) {
|
||||||
super(program, internalName);
|
super(program, internalName);
|
||||||
this.declaration = declaration;
|
this.declaration = declaration;
|
||||||
this.instances = new Map();
|
this.classPrototype = classPrototype;
|
||||||
this.isGeneric = declaration ? declaration.typeParameters.length > 0 : false; // builtins set this
|
this.isGeneric = declaration ? declaration.typeParameters.length > 0 : false; // builtins set this
|
||||||
}
|
}
|
||||||
|
|
||||||
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; }
|
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; }
|
||||||
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; }
|
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; }
|
||||||
|
get isInstance(): bool { return this.classPrototype != null; }
|
||||||
get isGetter(): bool { return this.declaration ? hasModifier(ModifierKind.GET, this.declaration.modifiers) : /* internals aren't getters */ false; }
|
get isGetter(): bool { return this.declaration ? hasModifier(ModifierKind.GET, this.declaration.modifiers) : /* internals aren't getters */ false; }
|
||||||
get isSetter(): bool { return this.declaration ? hasModifier(ModifierKind.SET, this.declaration.modifiers) : /* internals aren't setters */ false; }
|
get isSetter(): bool { return this.declaration ? hasModifier(ModifierKind.SET, this.declaration.modifiers) : /* internals aren't setters */ false; }
|
||||||
|
|
||||||
instantiate(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): FunctionInstance | null {
|
resolve(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): Function | null {
|
||||||
const instanceKey: string = typesToString(typeArguments, "", "");
|
const instanceKey: string = typesToString(typeArguments, "", "");
|
||||||
let instance: FunctionInstance | null = <FunctionInstance | null>this.instances.get(instanceKey);
|
let instance: Function | null = <Function | null>this.instances.get(instanceKey);
|
||||||
if (instance)
|
if (instance)
|
||||||
return instance;
|
return instance;
|
||||||
const declaration: FunctionDeclaration | null = this.declaration;
|
const declaration: FunctionDeclaration | null = this.declaration;
|
||||||
@ -793,31 +798,31 @@ export class FunctionTemplate extends Element {
|
|||||||
let internalName: string = this.internalName;
|
let internalName: string = this.internalName;
|
||||||
if (instanceKey.length)
|
if (instanceKey.length)
|
||||||
internalName += "<" + instanceKey + ">";
|
internalName += "<" + instanceKey + ">";
|
||||||
instance = new FunctionInstance(this, internalName, typeArguments, parameters, returnType, null); // TODO: class
|
instance = new Function(this, internalName, typeArguments, parameters, returnType, null); // TODO: class
|
||||||
this.instances.set(instanceKey, instance);
|
this.instances.set(instanceKey, instance);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FunctionInstance extends Element {
|
/** A resolved function. */
|
||||||
|
export class Function extends Element {
|
||||||
|
|
||||||
kind = ElementKind.FUNCTIONINSTANCE;
|
kind = ElementKind.FUNCTION;
|
||||||
template: FunctionTemplate;
|
template: FunctionPrototype;
|
||||||
typeArguments: Type[];
|
typeArguments: Type[];
|
||||||
parameters: Parameter[];
|
parameters: Parameter[];
|
||||||
returnType: Type;
|
returnType: Type;
|
||||||
instanceMethodOf: ClassInstance | null;
|
instanceMethodOf: Class | null;
|
||||||
locals: Map<string,Local> = new Map();
|
locals: Map<string,Local> = new Map();
|
||||||
additionalLocals: Type[] = [];
|
additionalLocals: Type[] = []; // without parameters
|
||||||
breakContext: string | null = null;
|
breakContext: string | null = null;
|
||||||
compiled: bool = false;
|
|
||||||
|
|
||||||
contextualTypeArguments: Map<string,Type> = new Map();
|
contextualTypeArguments: Map<string,Type> = new Map();
|
||||||
|
|
||||||
private breakMajor: i32 = 0;
|
private breakMajor: i32 = 0;
|
||||||
private breakMinor: i32 = 0;
|
private breakMinor: i32 = 0;
|
||||||
|
|
||||||
constructor(template: FunctionTemplate, internalName: string, typeArguments: Type[], parameters: Parameter[], returnType: Type, instanceMethodOf: ClassInstance | null) {
|
constructor(template: FunctionPrototype, internalName: string, typeArguments: Type[], parameters: Parameter[], returnType: Type, instanceMethodOf: Class | null) {
|
||||||
super(template.program, internalName);
|
super(template.program, internalName);
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.typeArguments = typeArguments;
|
this.typeArguments = typeArguments;
|
||||||
@ -866,20 +871,50 @@ export class FunctionInstance extends Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClassTemplate extends Namespace {
|
/** A yet unresolved instance field prototype. */
|
||||||
|
export class FieldPrototype extends Element {
|
||||||
|
|
||||||
kind = ElementKind.CLASS;
|
kind = ElementKind.FIELD_PROTOTYPE;
|
||||||
|
declaration: FieldDeclaration | null;
|
||||||
|
classPrototype: ClassPrototype;
|
||||||
|
|
||||||
|
constructor(classPrototype: ClassPrototype, internalName: string, declaration: FieldDeclaration | null) {
|
||||||
|
super(classPrototype.program, internalName);
|
||||||
|
this.classPrototype = classPrototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; }
|
||||||
|
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A resolved instance field. */
|
||||||
|
export class Field extends Element {
|
||||||
|
|
||||||
|
kind = ElementKind.FIELD;
|
||||||
|
template: FieldPrototype;
|
||||||
|
type: Type;
|
||||||
|
hasConstantValue: bool = false;
|
||||||
|
constantIntegerValue: I64 | null = null;
|
||||||
|
constantFloatValue: f64 = 0;
|
||||||
|
|
||||||
|
constructor(template: FieldPrototype, internalName: string, type: Type) {
|
||||||
|
super(template.program, internalName);
|
||||||
|
if (!this.template.declaration) this.hasConstantValue = true;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A yet unresolved class prototype. */
|
||||||
|
export class ClassPrototype extends Namespace {
|
||||||
|
|
||||||
|
kind = ElementKind.CLASS_PROTOTYPE;
|
||||||
declaration: ClassDeclaration | null;
|
declaration: ClassDeclaration | null;
|
||||||
fieldDeclarations: Map<string,FieldDeclaration>;
|
instances: Map<string,Class>;
|
||||||
methodDeclarations: Map<string,MethodDeclaration>;
|
|
||||||
instances: Map<string,ClassInstance>;
|
|
||||||
isGeneric: bool;
|
isGeneric: bool;
|
||||||
|
|
||||||
constructor(program: Program, internalName: string, declaration: ClassDeclaration | null = null) {
|
constructor(program: Program, internalName: string, declaration: ClassDeclaration | null = null) {
|
||||||
super(program, internalName, null);
|
super(program, internalName, null);
|
||||||
this.declaration = declaration;
|
this.declaration = declaration;
|
||||||
this.fieldDeclarations = new Map();
|
|
||||||
this.methodDeclarations = new Map();
|
|
||||||
this.instances = new Map();
|
this.instances = new Map();
|
||||||
this.isGeneric = declaration ? declaration.typeParameters.length > 0 : false; // builtins can set this
|
this.isGeneric = declaration ? declaration.typeParameters.length > 0 : false; // builtins can set this
|
||||||
}
|
}
|
||||||
@ -887,9 +922,9 @@ export class ClassTemplate extends Namespace {
|
|||||||
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; }
|
get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; }
|
||||||
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; }
|
get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; }
|
||||||
|
|
||||||
instantiate(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): ClassInstance {
|
resolve(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): Class {
|
||||||
const key: string = typesToString(typeArguments, "", "");
|
const key: string = typesToString(typeArguments, "", "");
|
||||||
let instance: ClassInstance | null = <ClassInstance | null>this.instances.get(key);
|
let instance: Class | null = <Class | null>this.instances.get(key);
|
||||||
if (instance)
|
if (instance)
|
||||||
return instance;
|
return instance;
|
||||||
if (!this.declaration)
|
if (!this.declaration)
|
||||||
@ -898,19 +933,20 @@ export class ClassTemplate extends Namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClassInstance extends Element {
|
/** A resolved class. */
|
||||||
|
export class Class extends Namespace {
|
||||||
|
|
||||||
kind = ElementKind.CLASSINSTANCE;
|
kind = ElementKind.CLASS;
|
||||||
template: ClassTemplate;
|
declaration: ClassDeclaration | null;
|
||||||
|
template: ClassPrototype;
|
||||||
typeArguments: Type[];
|
typeArguments: Type[];
|
||||||
base: ClassInstance | null;
|
base: Class | null;
|
||||||
type: Type;
|
type: Type;
|
||||||
compiled: bool = false;
|
|
||||||
|
|
||||||
contextualTypeArguments: Map<string,Type> = new Map();
|
contextualTypeArguments: Map<string,Type> = new Map();
|
||||||
|
|
||||||
constructor(template: ClassTemplate, internalName: string, typeArguments: Type[], base: ClassInstance | null) {
|
constructor(template: ClassPrototype, internalName: string, typeArguments: Type[], base: Class | null) {
|
||||||
super(template.program, internalName);
|
super(template.program, internalName, template.declaration);
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.typeArguments = typeArguments;
|
this.typeArguments = typeArguments;
|
||||||
this.base = base;
|
this.base = base;
|
||||||
@ -933,9 +969,10 @@ export class ClassInstance extends Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InterfaceTemplate extends ClassTemplate {
|
/** A yet unresvoled interface. */
|
||||||
|
export class InterfacePrototype extends ClassPrototype {
|
||||||
|
|
||||||
kind = ElementKind.INTERFACE;
|
kind = ElementKind.INTERFACE_PROTOTYPE;
|
||||||
declaration: InterfaceDeclaration | null;
|
declaration: InterfaceDeclaration | null;
|
||||||
|
|
||||||
constructor(program: Program, internalName: string, declaration: InterfaceDeclaration | null) {
|
constructor(program: Program, internalName: string, declaration: InterfaceDeclaration | null) {
|
||||||
@ -943,12 +980,14 @@ export class InterfaceTemplate extends ClassTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InterfaceInstance extends ClassInstance {
|
/** A resolved interface. */
|
||||||
|
export class Interface extends Class {
|
||||||
|
|
||||||
kind = ElementKind.INTERFACEINSTANCE;
|
kind = ElementKind.INTERFACE;
|
||||||
base: InterfaceInstance | null;
|
template: InterfacePrototype;
|
||||||
|
base: Interface | null;
|
||||||
|
|
||||||
constructor(template: InterfaceTemplate, internalName: string, typeArguments: Type[], base: InterfaceInstance | null) {
|
constructor(template: InterfacePrototype, internalName: string, typeArguments: Type[], base: Interface | null) {
|
||||||
super(template, internalName, typeArguments, base);
|
super(template, internalName, typeArguments, base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"compiler.ts",
|
"compiler.ts",
|
||||||
"diagnosticMessages.generated.ts",
|
"diagnosticMessages.generated.ts",
|
||||||
"diagnostics.ts",
|
"diagnostics.ts",
|
||||||
|
"evaluator.ts",
|
||||||
"glue/js.d.ts",
|
"glue/js.d.ts",
|
||||||
"glue/js.ts",
|
"glue/js.ts",
|
||||||
"index.ts",
|
"index.ts",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ClassInstance } from "./program";
|
import { Class } from "./program";
|
||||||
import { sb } from "./util";
|
import { sb } from "./util";
|
||||||
|
|
||||||
export const enum TypeKind {
|
export const enum TypeKind {
|
||||||
@ -29,7 +29,7 @@ export class Type {
|
|||||||
|
|
||||||
kind: TypeKind;
|
kind: TypeKind;
|
||||||
size: i32;
|
size: i32;
|
||||||
classType: ClassInstance | null;
|
classType: Class | null;
|
||||||
nullable: bool = false;
|
nullable: bool = false;
|
||||||
nullableType: Type | null = null; // cached, of this type
|
nullableType: Type | null = null; // cached, of this type
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ export class Type {
|
|||||||
get isAnySize(): bool { return this.kind == TypeKind.ISIZE || this.kind == TypeKind.USIZE; }
|
get isAnySize(): bool { return this.kind == TypeKind.ISIZE || this.kind == TypeKind.USIZE; }
|
||||||
get isAnyFloat(): bool { return this.kind == TypeKind.F32 || this.kind == TypeKind.F64; }
|
get isAnyFloat(): bool { return this.kind == TypeKind.F32 || this.kind == TypeKind.F64; }
|
||||||
|
|
||||||
asClass(classType: ClassInstance): Type {
|
asClass(classType: Class): Type {
|
||||||
const ret: Type = new Type(this.kind, this.size);
|
const ret: Type = new Type(this.kind, this.size);
|
||||||
ret.classType = classType;
|
ret.classType = classType;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
export { CharCode, isLineBreak} from "./util/charcode";
|
export { CharCode, isLineBreak} from "./util/charcode";
|
||||||
|
|
||||||
export { I64, U64 } from "./util/i64";
|
export { I64, U64 } from "./util/i64";
|
||||||
|
|
||||||
export { normalize as normalizePath, resolve as resolvePath, dirname } from "./util/path";
|
export { normalize as normalizePath, resolve as resolvePath, dirname } from "./util/path";
|
||||||
|
|
||||||
export const sb: string[] = new Array(256); // shared string builder. 64-bit without growing: (4+4+8) + 8*256 = 16b + 2kb
|
export const sb: string[] = new Array(256); // shared string builder. 64-bit without growing: (4+4+8) + 8*256 = 16b + 2kb
|
||||||
|
@ -30,6 +30,10 @@ const files: Map<string,string> = new Map([
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
import { sub } from "../other";
|
||||||
|
export function what(): void {
|
||||||
|
sub(1,2);
|
||||||
|
}
|
||||||
`],
|
`],
|
||||||
|
|
||||||
["../other",
|
["../other",
|
||||||
@ -54,6 +58,7 @@ do {
|
|||||||
const program = parser.finish();
|
const program = parser.finish();
|
||||||
const compiler = new Compiler(program);
|
const compiler = new Compiler(program);
|
||||||
const module = compiler.compile();
|
const module = compiler.compile();
|
||||||
|
console.log(program.elements.keys());
|
||||||
|
|
||||||
// module.optimize();
|
// module.optimize();
|
||||||
module.validate();
|
module.validate();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import "../src/glue/js";
|
import "../src/glue/js";
|
||||||
import { Tokenizer, Token } from "../src/tokenizer";
|
import { Tokenizer, Token } from "../src/tokenizer";
|
||||||
import { Source } from "../src/reflection";
|
import { Source } from "../src/ast";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
|
||||||
const text = fs.readFileSync(__dirname + "/../src/tokenizer.ts").toString();
|
const text = fs.readFileSync(__dirname + "/../src/tokenizer.ts").toString();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user