Skip to content

Commit

Permalink
Polishing
Browse files Browse the repository at this point in the history
 - Fix self compilation
 - Add strict property initialization flags for TS
 - Handle constructor inlining
  • Loading branch information
saulecabrera committed Mar 29, 2020
1 parent e16b6e5 commit 743ef7e
Show file tree
Hide file tree
Showing 40 changed files with 1,120 additions and 1,960 deletions.
246 changes: 123 additions & 123 deletions src/ast.ts

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,19 +597,19 @@ export namespace BuiltinNames {
/** Builtin compilation context. */
export class BuiltinContext {
/** Compiler reference. */
compiler: Compiler;
compiler!: Compiler;
/** Prototype being called. */
prototype: FunctionPrototype;
prototype!: FunctionPrototype;
/** Provided type arguments. */
typeArguments: Type[] | null;
typeArguments: Type[] | null = null;
/** Provided operands. */
operands: Expression[];
operands!: Expression[];
/** Contextual type. */
contextualType: Type;
contextualType!: Type;
/** Respective call expression. */
reportNode: CallExpression;
reportNode!: CallExpression;
/** Whether originating from inline assembly. */
contextIsExact: bool;
contextIsExact!: bool;
}

/** Global builtins map. */
Expand Down
13 changes: 7 additions & 6 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,13 @@ export class Compiler extends DiagnosticEmitter {
module: Module;

/** Current control flow. */
currentFlow: Flow;
currentFlow!: Flow;
/** Current parent element if not a function, i.e. an enum or namespace. */
currentParent: Element | null = null;
/** Current type in compilation. */
currentType: Type = Type.void;
/** Start function statements. */
currentBody: ExpressionRef[];
currentBody!: ExpressionRef[];
/** Counting memory offset. */
memoryOffset: i64;
/** Memory segments being compiled. */
Expand Down Expand Up @@ -2814,7 +2814,7 @@ export class Compiler extends DiagnosticEmitter {
outerFlow.popBreakLabel();

// If the switch has a default (guaranteed to handle any value), propagate common flags
if (defaultIndex >= 0){
if (defaultIndex >= 0) {
outerFlow.flags |= commonCategorical & ~FlowFlags.BREAKS;

// If the switch:
Expand All @@ -2826,7 +2826,7 @@ export class Compiler extends DiagnosticEmitter {
if (flows.length == 1) {
this.currentFlow.inheritFieldFlags(flows[0]);
} else {
for(let i = 0; i < flows.length; ++i) {
for (let i = 0; i < flows.length; ++i) {
if (i < (flows.length - 1)) {
const left = flows[i];
const right = flows[i + 1];
Expand Down Expand Up @@ -8900,7 +8900,6 @@ export class Compiler extends DiagnosticEmitter {
): ExpressionRef {
var ctor = this.ensureConstructor(classInstance, reportNode);
if (classInstance.type.isUnmanaged || ctor.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(reportNode);
this.checkFieldInitialization(classInstance);
var expr = this.compileCallDirect( // no need for another autoreleased local
ctor,
argumentExpressions,
Expand All @@ -8911,6 +8910,8 @@ export class Compiler extends DiagnosticEmitter {
if (getExpressionType(expr) != NativeType.None) { // possibly IMM_DROPPED
this.currentType = classInstance.type; // important because a super ctor could be called
}

this.checkFieldInitialization(classInstance);
return expr;
}

Expand Down Expand Up @@ -10119,7 +10120,7 @@ export class Compiler extends DiagnosticEmitter {
field.memoryOffset
)
);
flow.setFieldFlag(field.internalName, FieldFlags.INITIALIZED)
flow.setFieldFlag(field.internalName, FieldFlags.INITIALIZED);
} else {
flow.setFieldFlag(field.internalName, FieldFlags.NONE);
}
Expand Down
2 changes: 1 addition & 1 deletion src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export abstract class ExportsWalker {
/** Constructs a new Element walker. */
constructor(program: Program, includePrivate: bool = false) {
this.program = program;
this.includePrivate;
this.includePrivate = includePrivate;
}

/** Walks all elements and calls the respective handlers. */
Expand Down
40 changes: 21 additions & 19 deletions src/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,43 +189,36 @@ export const enum ConditionKind {
export class Flow {

/** Parent flow. */
parent: Flow | null;
parent: Flow | null = null;
/** Flow flags indicating specific conditions. */
flags: FlowFlags;
flags: FlowFlags = FlowFlags.NONE;
/** Function this flow belongs to. */
parentFunction: Function;
parentFunction!: Function;
/** The label we break to when encountering a continue statement. */
continueLabel: string | null;
continueLabel: string | null = null;
/** The label we break to when encountering a break statement. */
breakLabel: string | null;
breakLabel: string | null = null;
/** The current return type. */
returnType: Type;
returnType!: Type;
/** The current contextual type arguments. */
contextualTypeArguments: Map<string,Type> | null;
contextualTypeArguments: Map<string,Type> | null = null;
/** Scoped local variables. */
scopedLocals: Map<string,Local> | null = null;
/** Local flags. */
localFlags: LocalFlags[];
localFlags: LocalFlags[] = [];
/** Field flags. */
fieldFlags: Map<string, FieldFlags> | null = null;
/** Function being inlined, when inlining. */
inlineFunction: Function | null;
inlineFunction: Function | null = null;
/** The label we break to when encountering a return statement, when inlining. */
inlineReturnLabel: string | null;
inlineReturnLabel: string | null = null;

/** Creates the parent flow of the specified function. */
static create(parentFunction: Function): Flow {
var flow = new Flow();
flow.parent = null;
flow.flags = FlowFlags.NONE;
flow.parentFunction = parentFunction;
flow.continueLabel = null;
flow.breakLabel = null;
flow.returnType = parentFunction.signature.returnType;
flow.contextualTypeArguments = parentFunction.contextualTypeArguments;
flow.localFlags = [];
flow.inlineFunction = null;
flow.inlineReturnLabel = null;

if (flow.actualFunction.is(CommonFlags.CONSTRUCTOR)) {
flow.fieldFlags = new Map();
Expand All @@ -240,6 +233,7 @@ export class Flow {
flow.inlineReturnLabel = inlineFunction.internalName + "|inlined." + (inlineFunction.nextInlineId++).toString();
flow.returnType = inlineFunction.signature.returnType;
flow.contextualTypeArguments = inlineFunction.contextualTypeArguments;
flow.fieldFlags = inlineFunction.flow.fieldFlags;
return flow;
}

Expand Down Expand Up @@ -536,14 +530,16 @@ export class Flow {
localFlags[index] = flags & ~flag;
}

/** Associates the given flag with the given field name */
setFieldFlag(name: string, flag: FieldFlags): void {
let fieldFlags = this.fieldFlags;
var fieldFlags = this.fieldFlags;
if (fieldFlags) {
const flags = fieldFlags.has(name) ? assert(fieldFlags.get(name)) : FieldFlags.NONE;
fieldFlags.set(name, flags | flag);
}
}

/** Tests if the given field name and flag exist */
isFieldFlag(name: string, flag: FieldFlags): bool {
const fieldFlags = this.fieldFlags;

Expand Down Expand Up @@ -845,6 +841,11 @@ export class Flow {
this.mergeFieldFlags(left, right);
}

/**
* Merges the fields flags of the given flows
* into the current flow. Flags will only be merged
* if both flows definitely define the flags.
*/
mergeFieldFlags(left: Flow, right: Flow): void {
if (left.fieldFlags !== null &&
right.fieldFlags !== null &&
Expand All @@ -870,6 +871,7 @@ export class Flow {
}
}

/** Inherits the fields flags of the given flow into the current flow */
inheritFieldFlags(other: Flow): void {
if (
this.fieldFlags !== null &&
Expand All @@ -884,7 +886,7 @@ export class Flow {
const key = otherKeys[i];
const otherValue = otherValues[i];
if (otherValue & FieldFlags.INITIALIZED) {
currentFieldFlags.set(key, FieldFlags.INITIALIZED)
currentFieldFlags.set(key, FieldFlags.INITIALIZED);
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,8 @@ export enum SIMDLoadOp {

export class MemorySegment {

buffer: Uint8Array;
offset: i64;
buffer!: Uint8Array;
offset!: i64;

static create(buffer: Uint8Array, offset: i64): MemorySegment {
var segment = new MemorySegment();
Expand All @@ -481,9 +481,9 @@ export class MemorySegment {

export class Module {

ref: ModuleRef;
ref!: ModuleRef;

private lit: usize;
private lit!: usize;

static create(): Module {
var module = new Module();
Expand Down Expand Up @@ -1896,8 +1896,8 @@ export function getEventResults(event: EventRef): NativeType {

export class Relooper {

module: Module;
ref: RelooperRef;
module!: Module;
ref!: RelooperRef;

static create(module: Module): Relooper {
var relooper = new Relooper();
Expand Down Expand Up @@ -2141,9 +2141,9 @@ export function readString(ptr: usize): string | null {
/** Result structure of {@link Module#toBinary}. */
export class BinaryModule {
/** WebAssembly binary. */
output: Uint8Array;
output!: Uint8Array;
/** Source map, if generated. */
sourceMap: string | null;
sourceMap: string | null = null;
}

/** Tests if an expression needs an explicit 'unreachable' when it is the terminating statement. */
Expand Down
2 changes: 1 addition & 1 deletion src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class Parser extends DiagnosticEmitter {
/** Optional handler to intercept comments while tokenizing. */
onComment: CommentHandler | null = null;
/** Current file being parsed. */
currentSource: Source;
currentSource!: Source;
/** Dependency map **/
dependees: Map<string, Source> = new Map();

Expand Down
64 changes: 32 additions & 32 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,68 +448,68 @@ export class Program extends DiagnosticEmitter {
// standard references

/** ArrayBufferView reference. */
arrayBufferViewInstance: Class;
arrayBufferViewInstance!: Class;
/** ArrayBuffer instance reference. */
arrayBufferInstance: Class;
arrayBufferInstance!: Class;
/** Array prototype reference. */
arrayPrototype: ClassPrototype;
arrayPrototype!: ClassPrototype;
/** Static array prototype reference. */
staticArrayPrototype: ClassPrototype;
staticArrayPrototype!: ClassPrototype;
/** Set prototype reference. */
setPrototype: ClassPrototype;
setPrototype!: ClassPrototype;
/** Map prototype reference. */
mapPrototype: ClassPrototype;
mapPrototype!: ClassPrototype;
/** Int8Array prototype. */
i8ArrayPrototype: ClassPrototype;
i8ArrayPrototype!: ClassPrototype;
/** Int16Array prototype. */
i16ArrayPrototype: ClassPrototype;
i16ArrayPrototype!: ClassPrototype;
/** Int32Array prototype. */
i32ArrayPrototype: ClassPrototype;
i32ArrayPrototype!: ClassPrototype;
/** Int64Array prototype. */
i64ArrayPrototype: ClassPrototype;
i64ArrayPrototype!: ClassPrototype;
/** Uint8Array prototype. */
u8ArrayPrototype: ClassPrototype;
u8ArrayPrototype!: ClassPrototype;
/** Uint8ClampedArray prototype. */
u8ClampedArrayPrototype: ClassPrototype;
u8ClampedArrayPrototype!: ClassPrototype;
/** Uint16Array prototype. */
u16ArrayPrototype: ClassPrototype;
u16ArrayPrototype!: ClassPrototype;
/** Uint32Array prototype. */
u32ArrayPrototype: ClassPrototype;
u32ArrayPrototype!: ClassPrototype;
/** Uint64Array prototype. */
u64ArrayPrototype: ClassPrototype;
u64ArrayPrototype!: ClassPrototype;
/** Float32Array prototype. */
f32ArrayPrototype: ClassPrototype;
f32ArrayPrototype!: ClassPrototype;
/** Float64Array prototype. */
f64ArrayPrototype: ClassPrototype;
f64ArrayPrototype!: ClassPrototype;
/** String instance reference. */
stringInstance: Class;
stringInstance!: Class;
/** Abort function reference, if not explicitly disabled. */
abortInstance: Function | null;
abortInstance: Function | null = null;

// runtime references

/** RT `__alloc(size: usize, id: u32): usize` */
allocInstance: Function;
allocInstance!: Function;
/** RT `__realloc(ptr: usize, newSize: usize): usize` */
reallocInstance: Function;
reallocInstance!: Function;
/** RT `__free(ptr: usize): void` */
freeInstance: Function;
freeInstance!: Function;
/** RT `__retain(ptr: usize): usize` */
retainInstance: Function;
retainInstance!: Function;
/** RT `__release(ptr: usize): void` */
releaseInstance: Function;
releaseInstance!: Function;
/** RT `__collect(): void` */
collectInstance: Function;
collectInstance!: Function;
/** RT `__visit(ptr: usize, cookie: u32): void` */
visitInstance: Function;
visitInstance!: Function;
/** RT `__typeinfo(id: u32): RTTIFlags` */
typeinfoInstance: Function;
typeinfoInstance!: Function;
/** RT `__instanceof(ptr: usize, superId: u32): bool` */
instanceofInstance: Function;
instanceofInstance!: Function;
/** RT `__allocBuffer(size: usize, id: u32, data: usize = 0): usize` */
allocBufferInstance: Function;
allocBufferInstance!: Function;
/** RT `__allocArray(length: i32, alignLog2: usize, id: u32, data: usize = 0): usize` */
allocArrayInstance: Function;
allocArrayInstance!: Function;

/** Next class id. */
nextClassId: u32 = 0;
Expand Down Expand Up @@ -2695,9 +2695,9 @@ export abstract class VariableLikeElement extends TypedElement {
/** Constant value kind. */
constantValueKind: ConstantValueKind = ConstantValueKind.NONE;
/** Constant integer value, if applicable. */
constantIntegerValue: i64;
constantIntegerValue!: i64;
/** Constant float value, if applicable. */
constantFloatValue: f64;
constantFloatValue!: f64;

/** Constructs a new variable-like element. */
protected constructor(
Expand Down
6 changes: 3 additions & 3 deletions src/tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1567,11 +1567,11 @@ export class Tokenizer extends DiagnosticEmitter {
/** Tokenizer state as returned by {@link Tokenizer#mark} and consumed by {@link Tokenizer#reset}. */
export class State {
/** Current position. */
pos: i32;
pos!: i32;
/** Current token. */
token: Token;
token!: Token;
/** Current token's position. */
tokenPos: i32;
tokenPos!: i32;
}

// Reusable state object to reduce allocations
Expand Down

0 comments on commit 743ef7e

Please sign in to comment.