Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3593,6 +3593,11 @@ export function compileCall(
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.u32;
if (!type) return module.unreachable();

if (type.is(TypeFlags.REFERENCE) && type.signatureReference !== null) {
return module.i32(type.signatureReference.id);
}

let classReference = type.classReference;
if (!classReference || classReference.hasDecorator(DecoratorFlags.UNMANAGED)) {
compiler.error(
Expand Down
9 changes: 5 additions & 4 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ export class Compiler extends DiagnosticEmitter {
program.initialize(options);

// set up the main start function
var startFunctionInstance = program.makeNativeFunction("start", new Signature([], Type.void));
var startFunctionInstance = program.makeNativeFunction("start", new Signature(program, [], Type.void));
startFunctionInstance.internalName = "start";
var startFunctionBody = new Array<ExpressionRef>();
this.currentFlow = startFunctionInstance.flow;
Expand Down Expand Up @@ -6367,7 +6367,7 @@ export class Compiler extends DiagnosticEmitter {
assert(operandIndex == minOperands);

// create the trampoline element
var trampolineSignature = new Signature(originalParameterTypes, returnType, thisType);
var trampolineSignature = new Signature(this.program, originalParameterTypes, returnType, thisType);
trampolineSignature.requiredParameters = maxArguments;
trampolineSignature.parameterNames = originalSignature.parameterNames;
trampoline = new Function(
Expand Down Expand Up @@ -7082,7 +7082,7 @@ export class Compiler extends DiagnosticEmitter {
}
}

let signature = new Signature(parameterTypes, returnType, thisType);
let signature = new Signature(this.program, parameterTypes, returnType, thisType);
signature.requiredParameters = numParameters; // !
signature.parameterNames = parameterNames;
instance = new Function(
Expand Down Expand Up @@ -7845,7 +7845,7 @@ export class Compiler extends DiagnosticEmitter {
CommonFlags.INSTANCE | CommonFlags.CONSTRUCTOR
)
),
new Signature(null, classInstance.type, classInstance.type),
new Signature(this.program, null, classInstance.type, classInstance.type),
null
);
}
Expand Down Expand Up @@ -9009,6 +9009,7 @@ export class Compiler extends DiagnosticEmitter {
flow.popBreakLabel();
return module.block(label, conditions, NativeType.I32);
}

}

// helpers
Expand Down
7 changes: 5 additions & 2 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ export class Program extends DiagnosticEmitter {
typeClasses: Map<TypeKind,Class> = new Map();
/** Managed classes contained in the program, by id. */
managedClasses: Map<i32,Class> = new Map();
/** A set of unique function signatures contained in the program, by id. */
uniqueSignatures: Signature[] = new Array<Signature>(0);

// standard references

Expand Down Expand Up @@ -403,7 +405,8 @@ export class Program extends DiagnosticEmitter {

/** Next class id. */
nextClassId: u32 = 0;

/** Next signature id. */
nextSignatureId: i32 = 0;
/** Constructs a new program, optionally inheriting parser diagnostics. */
constructor(
/** Shared array of diagnostic messages (emitted so far). */
Expand Down Expand Up @@ -2141,7 +2144,7 @@ export class File extends Element {
program.filesByName.set(this.internalName, this);
var startFunction = this.program.makeNativeFunction(
"start:" + this.internalName,
new Signature(null, Type.void),
new Signature(program, null, Type.void),
this
);
startFunction.internalName = startFunction.name;
Expand Down
4 changes: 2 additions & 2 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ export class Resolver extends DiagnosticEmitter {
);
if (!returnType) return null;
}
var signature = new Signature(parameterTypes, returnType, thisType);
var signature = new Signature(this.program, parameterTypes, returnType, thisType);
signature.parameterNames = parameterNames;
signature.requiredParameters = requiredParameters;
signature.hasRest = hasRest;
Expand Down Expand Up @@ -1551,7 +1551,7 @@ export class Resolver extends DiagnosticEmitter {
returnType = type;
}

var signature = new Signature(parameterTypes, returnType, thisType);
var signature = new Signature(this.program, parameterTypes, returnType, thisType);
signature.parameterNames = parameterNames;
signature.requiredParameters = requiredParameters;

Expand Down
32 changes: 27 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,8 @@ export function typesToString(types: Type[]): string {

/** Represents a fully resolved function signature. */
export class Signature {

/** The unique program id that represents this signature. */
id: u32 = 0;
/** Parameter types, if any, excluding `this`. */
parameterTypes: Type[];
/** Parameter names, if known, excluding `this`. */
Expand All @@ -573,9 +574,12 @@ export class Signature {
cachedFunctionTarget: FunctionTarget | null = null;
/** Respective function type. */
type: Type;
/** The program that created this signature. */
program: Program;

/** Constructs a new signature. */
constructor(
program: Program,
parameterTypes: Type[] | null = null,
returnType: Type | null = null,
thisType: Type | null = null
Expand All @@ -585,8 +589,21 @@ export class Signature {
this.requiredParameters = 0;
this.returnType = returnType ? returnType : Type.void;
this.thisType = thisType;
this.program = program;
this.hasRest = false;
this.type = Type.u32.asFunction(this);

let signatureTypes = program.uniqueSignatures;
let length = signatureTypes.length;
for (let i = 0; i < length; i++) {
let compare = signatureTypes[i];
if (this.equals(compare)) {
this.id = compare.id;
return this;
}
}
program.uniqueSignatures.push(this);
this.id = program.nextSignatureId++;
}

asFunctionTarget(program: Program): FunctionTarget {
Expand All @@ -606,23 +623,28 @@ export class Signature {

/** Tests if a value of this function type is assignable to a target of the specified function type. */
isAssignableTo(target: Signature): bool {
return this.equals(target);
}

/** Tests to see if a signature equals another signature. */
equals(value: Signature): bool {
// TODO: maybe cache results?

// check `this` type
var thisThisType = this.thisType;
var targetThisType = target.thisType;
var targetThisType = value.thisType;
if (thisThisType) {
if (!(targetThisType && thisThisType.isAssignableTo(targetThisType))) return false;
} else if (targetThisType) {
return false;
}

// check rest parameter
if (this.hasRest != target.hasRest) return false; // TODO
if (this.hasRest != value.hasRest) return false; // TODO

// check parameter types
var thisParameterTypes = this.parameterTypes;
var targetParameterTypes = target.parameterTypes;
var targetParameterTypes = value.parameterTypes;
var numParameters = thisParameterTypes.length;
if (numParameters != targetParameterTypes.length) return false;
for (let i = 0; i < numParameters; ++i) {
Expand All @@ -633,7 +655,7 @@ export class Signature {

// check return type
var thisReturnType = this.returnType;
var targetReturnType = target.returnType;
var targetReturnType = value.returnType;
return thisReturnType == targetReturnType || thisReturnType.isAssignableTo(targetReturnType);
}

Expand Down
2 changes: 0 additions & 2 deletions tests/compiler/binary.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
local.get $2
i32.wrap_i64
i32.const 0
i32.ne
i32.const 0
local.get $1
i32.const 2147483647
i32.and
Expand Down
28 changes: 20 additions & 8 deletions tests/compiler/builtins.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
(type $FUNCSIG$if (func (param f32) (result i32)))
(type $FUNCSIG$id (func (param f64) (result i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
(type $FUNCSIG$viiddddd (func (param i32 i32 f64 f64 f64 f64 f64)))
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(import "env" "trace" (func $~lib/builtins/trace (param i32 i32 f64 f64 f64 f64 f64)))
(memory $0 1)
(data (i32.const 12) "\01\00\00\00\01")
(data (i32.const 24) "\06\00\00\00\01\00\00\00\01\00\00\00\06\00\00\00a\00b\00c")
(data (i32.const 48) "\16\00\00\00\01\00\00\00\01\00\00\00\16\00\00\00b\00u\00i\00l\00t\00i\00n\00s\00.\00t\00s")
(data (i32.const 88) "\14\00\00\00\01\00\00\00\01\00\00\00\14\00\00\00s\00i\00g\00n\00a\00t\00u\00r\00e\00s")
(data (i32.const 128) "\0e\00\00\00\01\00\00\00\01\00\00\00\0e\00\00\00t\00e\00s\00t\00i\00n\00g")
(table $0 2 funcref)
(elem (i32.const 0) $builtins/test $start:builtins~anonymous|0)
(global $builtins/b (mut i32) (i32.const 0))
Expand All @@ -23,34 +27,34 @@
(export "memory" (memory $0))
(export "test" (func $builtins/test))
(start $start)
(func $~lib/number/isNaN<f32> (; 1 ;) (type $FUNCSIG$if) (param $0 f32) (result i32)
(func $~lib/number/isNaN<f32> (; 2 ;) (type $FUNCSIG$if) (param $0 f32) (result i32)
local.get $0
local.get $0
f32.ne
)
(func $~lib/number/isFinite<f32> (; 2 ;) (type $FUNCSIG$if) (param $0 f32) (result i32)
(func $~lib/number/isFinite<f32> (; 3 ;) (type $FUNCSIG$if) (param $0 f32) (result i32)
local.get $0
local.get $0
f32.sub
f32.const 0
f32.eq
)
(func $~lib/number/isNaN<f64> (; 3 ;) (type $FUNCSIG$id) (param $0 f64) (result i32)
(func $~lib/number/isNaN<f64> (; 4 ;) (type $FUNCSIG$id) (param $0 f64) (result i32)
local.get $0
local.get $0
f64.ne
)
(func $~lib/number/isFinite<f64> (; 4 ;) (type $FUNCSIG$id) (param $0 f64) (result i32)
(func $~lib/number/isFinite<f64> (; 5 ;) (type $FUNCSIG$id) (param $0 f64) (result i32)
local.get $0
local.get $0
f64.sub
f64.const 0
f64.eq
)
(func $start:builtins~anonymous|0 (; 5 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
(func $start:builtins~anonymous|0 (; 6 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
nop
)
(func $start:builtins (; 6 ;) (type $FUNCSIG$v)
(func $start:builtins (; 7 ;) (type $FUNCSIG$v)
i32.const 31
global.set $builtins/i
i32.const 0
Expand Down Expand Up @@ -685,11 +689,19 @@
i32.const 8
f64.const 1
f64.store
i32.const 104
i32.const 5
f64.const 0
f64.const 0
f64.const 12
f64.const 27
f64.const 27
call $~lib/builtins/trace
)
(func $builtins/test (; 7 ;) (type $FUNCSIG$v)
(func $builtins/test (; 8 ;) (type $FUNCSIG$v)
nop
)
(func $start (; 8 ;) (type $FUNCSIG$v)
(func $start (; 9 ;) (type $FUNCSIG$v)
call $start:builtins
)
)
15 changes: 15 additions & 0 deletions tests/compiler/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,18 @@ f64.store(8, 1.0);

f32.trunc(1.0);
f64.trunc(1.0);


{
let a = idof<() => void>();
let b = idof<() => void>();
let c = idof<(a: u32) => void>();
let d = idof<(val: C) => C>();
let e = idof<(val2: C) => C>();
trace("signatures", 5, a, b, c, d, e);

assert(a == b, "testing");
assert(a != c);
assert(c == idof<(b: u32) => void>());
assert(d == e);
}
Loading