Skip to content
Open
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
8 changes: 4 additions & 4 deletions src/benchmark/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,16 @@ const mergeSortFunc = {
['mergeSortCopyArray', { parameterTypes: [WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32,
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32 }],
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32_ARRAY }],
['mergeSort', { parameterTypes: [WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32,
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32 }],
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32_ARRAY }],
['mergeSortMerge', { parameterTypes: [WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32,
WebAssemblyType.INT_32,
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32 }],
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32_ARRAY }],
['mergeSortIsSorted', { parameterTypes: [WebAssemblyType.INT_32_ARRAY], returnType: WebAssemblyType.BOOLEAN }],
['mergeSortFill', { parameterTypes: [WebAssemblyType.INT_32_ARRAY], returnType: WebAssemblyType.INT_32 }],
['mergeSortWhile', { parameterTypes: [WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32_ARRAY],
Expand All @@ -126,7 +126,7 @@ const quicksortFunc = {
WebAssemblyType.INT_32,
WebAssemblyType.INT_32], returnType: WebAssemblyType.INT_32 }],
['quickSort', { parameterTypes: [WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32, WebAssemblyType.INT_32],
returnType: WebAssemblyType.INT_32 }],
returnType: WebAssemblyType.INT_32_ARRAY }],
['quickSortFill', { parameterTypes: [WebAssemblyType.INT_32_ARRAY], returnType: WebAssemblyType.INT_32 }],
['quickSortIsSorted', { parameterTypes: [WebAssemblyType.INT_32_ARRAY], returnType: WebAssemblyType.BOOLEAN }],
['quickSortWhile', { parameterTypes: [WebAssemblyType.INT_32_ARRAY], returnType: WebAssemblyType.BOOLEAN }],
Expand Down
2 changes: 1 addition & 1 deletion src/generator/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Generator {

const totalMapping = Generator.mergeMappings(parameterMapping, variableMapping);

const generatorVisitor = new GeneratorVisitor(module, totalMapping, expressionTypes, signatures);
const generatorVisitor = new GeneratorVisitor(module, totalMapping, expressionTypes, signatures, signature);
const body = generatorVisitor.run(tree);

const {parameterTypes, returnType} = signature;
Expand Down
19 changes: 14 additions & 5 deletions src/generator/generator_visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import {Expression, Module, Statement} from 'binaryen';
import CallWrapper from '../call_wrapper';
import Visitor from '../visitor';
import {VariableMapping} from './declaration_visitor';
import {FunctionSignature, FunctionSignatures} from './generator';
import {ExpressionTypes} from './type_inference_visitor';
import {getCommonType, toBinaryenType, WebAssemblyType} from './wasm_type';
import {FunctionSignatures} from './generator';
import {getCommonType, isTypeCompatible, toBinaryenType, WebAssemblyType} from './wasm_type';

type BinaryExpressionFunction = (first: Expression, second: Expression) => Expression;

Expand All @@ -42,6 +42,7 @@ class GeneratorVisitor extends Visitor {
private readonly variableMapping: VariableMapping;
private readonly expressionTypes: ExpressionTypes;
private readonly signatures: FunctionSignatures;
private readonly signature: FunctionSignature;

private statements: Statement[] = [];
private expressions: Expression[] = [];
Expand All @@ -51,13 +52,15 @@ class GeneratorVisitor extends Visitor {
constructor(module: Module,
variableMapping: VariableMapping,
expressionType: ExpressionTypes,
signatures: FunctionSignatures) {
signatures: FunctionSignatures,
signature: FunctionSignature) {

super();
this.module = module;
this.variableMapping = variableMapping;
this.expressionTypes = expressionType;
this.signatures = signatures;
this.signature = signature;
}

public run(tree: FunctionDeclaration): Statement {
Expand All @@ -83,8 +86,14 @@ class GeneratorVisitor extends Visitor {
protected visitReturnStatement(node: ReturnStatement) {
super.visitReturnStatement(node);

const returnStatement = this.module.return(this.expressions.pop());
this.statements.push(returnStatement);
if (node.argument !== null) {
if (!isTypeCompatible(this.getExpressionType(node.argument), this.signature.returnType)) {
throw new Error(`Returned value is not compatible with ` +
`returntype ${WebAssemblyType[this.signature.returnType]}`);
}
}

this.statements.push(this.module.return(this.popExpression()));
}

protected visitUnaryExpression(node: UnaryExpression) {
Expand Down
8 changes: 7 additions & 1 deletion src/generator/wasm_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ function getCommonType(first: WebAssemblyType, second: WebAssemblyType) {
}
}

function isTypeCompatible(toCheck: WebAssemblyType, type: WebAssemblyType) {
return (toCheck === type) ||
(toCheck === WebAssemblyType.INT_32 && type === WebAssemblyType.FLOAT_64) ||
(toCheck === WebAssemblyType.INT_32_ARRAY && type === WebAssemblyType.FLOAT_64_ARRAY);
}

function isOfType(toCheck: any, type: WebAssemblyType) {
switch (type) {
case WebAssemblyType.INT_32:
Expand Down Expand Up @@ -88,4 +94,4 @@ function isArray(value: any, type: WebAssemblyType) {
}
}

export {WebAssemblyType, toBinaryenType, getNumberType, getCommonType, isOfType};
export {WebAssemblyType, toBinaryenType, getNumberType, getCommonType, isTypeCompatible, isOfType};
8 changes: 4 additions & 4 deletions test/time_limited/transpiler_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe('Transpiler', function() {
WebAssemblyType.INT_32, WebAssemblyType.INT_32)
.setSignature('quickSortPartition', WebAssemblyType.INT_32, WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32, WebAssemblyType.INT_32)
.setSignature('quickSort', WebAssemblyType.INT_32, WebAssemblyType.INT_32_ARRAY,
.setSignature('quickSort', WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32, WebAssemblyType.INT_32)
.setSignature('quickSortFill', WebAssemblyType.INT_32, WebAssemblyType.INT_32_ARRAY)
.setSignature('quickSortIsSorted', WebAssemblyType.BOOLEAN, WebAssemblyType.INT_32_ARRAY)
Expand All @@ -101,11 +101,11 @@ describe('Transpiler', function() {
const content = mergeSortCopyArray.toString() + mergeSort.toString() + mergeSortMerge.toString() +
mergeSortIsSorted.toString() + mergeSortFill.toString() + mergeSortWhile.toString();
const wrapper = transpiler
.setSignature('mergeSortCopyArray', WebAssemblyType.INT_32, WebAssemblyType.INT_32_ARRAY,
.setSignature('mergeSortCopyArray', WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32, WebAssemblyType.INT_32)
.setSignature('mergeSort', WebAssemblyType.INT_32, WebAssemblyType.INT_32_ARRAY,
.setSignature('mergeSort', WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32, WebAssemblyType.INT_32)
.setSignature('mergeSortMerge', WebAssemblyType.INT_32, WebAssemblyType.INT_32_ARRAY,
.setSignature('mergeSortMerge', WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32_ARRAY,
WebAssemblyType.INT_32_ARRAY, WebAssemblyType.INT_32, WebAssemblyType.INT_32,
WebAssemblyType.INT_32)
.setSignature('mergeSortIsSorted', WebAssemblyType.BOOLEAN, WebAssemblyType.INT_32_ARRAY)
Expand Down
12 changes: 2 additions & 10 deletions test/transpiler/transpiler_function_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,9 @@ describe('Transpiler', () => {
});

it('should handle function call with not matching return type conversion', () => {
const content = 'function func(value) { return value; }';

const wrapper = transpiler
expect(() => transpiler
.setSignature('func', WebAssemblyType.BOOLEAN, WebAssemblyType.INT_32)
.transpile(content);
wrapper.setFunctionName('func');

expect(wrapper.call(1)).to.equal(true);
expect(wrapper.call(0)).to.equal(false);
expect(() => wrapper.call(2)).to.throw();
expect(() => wrapper.call(-1)).to.throw();
.transpile('function func(value) { return value; }')).to.throw();
});

it('should handle different types for one variable', () => {
Expand Down
18 changes: 18 additions & 0 deletions test/transpiler/transpiler_literal_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,23 @@ describe('Transpiler', () => {
.transpile('function alwaysFalse() { return false; }');
expect(wrapper2.setFunctionName('alwaysFalse').call()).to.equal(false);
});

it('should handle integer as boolean values', () => {
expect(() => transpiler
.setSignature('integer', WebAssemblyType.BOOLEAN)
.transpile('function integer() { return 0; }')).to.throw();

expect(() => new Transpiler()
.setSignature('integer', WebAssemblyType.BOOLEAN)
.transpile('function integer() { return 1; }')).to.throw();

expect(() => new Transpiler()
.setSignature('integer', WebAssemblyType.BOOLEAN)
.transpile('function integer() { return 2; }')).to.throw();

expect(() => new Transpiler()
.setSignature('integer', WebAssemblyType.BOOLEAN)
.transpile('function integer() { return -2; }')).to.throw();
});
});
});
19 changes: 19 additions & 0 deletions test/transpiler/transpiler_variable_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,26 @@ describe('Transpiler', () => {
expect(wrapper.setFunctionName('variables').call(100)).to.equal(10);
});

it('should handle boolean parameters', () => {
const content = 'function variables(x) { return x; }';
const wrapper = transpiler
.setSignature('variables', WebAssemblyType.BOOLEAN, WebAssemblyType.BOOLEAN)
.transpile(content);

expect(wrapper.setFunctionName('variables').call(true)).to.equal(true);
expect(wrapper.setFunctionName('variables').call(false)).to.equal(false);
});

it('should handle boolean variable', () => {
const content = 'function variables() { var x = true; return x; }';
const wrapper = transpiler
.setSignature('variables', WebAssemblyType.BOOLEAN)
.transpile(content);

expect(wrapper.setFunctionName('variables').call()).to.equal(true);
});

it('should handle boolean variables in expression', () => {
const content = 'function variables() { var x = true; var y; y = false; return x || y; }';
const wrapper = transpiler
.setSignature('variables', WebAssemblyType.BOOLEAN)
Expand Down