Skip to content

Commit

Permalink
New Release
Browse files Browse the repository at this point in the history
  • Loading branch information
ghadeeras committed Dec 1, 2024
0 parents commit 6cee7ca
Show file tree
Hide file tree
Showing 30 changed files with 2,636 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.nyc_output
coverage
node_modules
lib
tsconfig.tsbuildinfo
release.sh
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Vibrato.js
![ci-build](https://github.com/ghadeeras/vibrato.js/workflows/ci-build/badge.svg)

Much like the [Vibrato](https://ghadeeras.github.io/vibrato) project targets the Java programming language, this is a similar digital signal processing library (or a computation library) for the JavaScript or TypeScript programming languages. The concept is a little different though. Vibrato.js is meant to be like an intermediate representation (IR) for a minimal functional DSP language that compiles to a WebAssembly module, which then can be referenced by a JavaScript module.

The project is still in its infancy. It will take a while before it reaches the stage of a viable product. So again, please bear with me :-)

## Sub-Modules
* [The Runtime Core Library](docs/rt.md)
* [The Web Assembly Loader](docs/wa.md)
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
theme: jekyll-theme-midnight
4 changes: 4 additions & 0 deletions docs/rt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Vibrato.js

## The Runtime Core Library
A tier written entirely in WebAssembly that is the runtime core library for modules created by Vibrato.js
4 changes: 4 additions & 0 deletions docs/wa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Vibrato.js

## The Web Assembly Loader
A simple library to facilitate loading and instantiating web assembly modules.
Binary file added latest.zip
Binary file not shown.
18 changes: 18 additions & 0 deletions latest/js/assembler.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as exps from './expressions.js';
import * as rt from './rt-node.js';
export declare class Assembler {
readonly rawMemTextCode: string;
readonly rawMemBinaryCode: Uint8Array;
readonly nonOptimizedTextCode: string;
readonly nonOptimizedBinaryCode: Uint8Array;
readonly textCode: string;
readonly binaryCode: Uint8Array;
constructor(expressions: exps.Expression[]);
private newModule;
private organizeMemory;
private declareCycleFunction;
private declareExpressionFunctions;
private validate;
get rawMem(): ArrayBufferLike;
exports<E extends WebAssembly.Exports>(rt: rt.Runtime): E;
}
138 changes: 138 additions & 0 deletions latest/js/assembler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import * as wa from './wa.js';
import * as rt from './rt-node.js';
import binaryen from 'binaryen';
export class Assembler {
constructor(expressions) {
const allExpressions = flatten(expressions);
const rawMemModule = this.newModule(false);
const module = this.newModule(true);
try {
this.organizeMemory(rawMemModule, allExpressions);
this.validate(rawMemModule);
rawMemModule.optimize();
this.rawMemTextCode = rawMemModule.emitText();
this.rawMemBinaryCode = rawMemModule.emitBinary();
this.declareCycleFunction(module, allExpressions);
this.declareExpressionFunctions(module, allExpressions);
this.validate(module);
this.nonOptimizedTextCode = module.emitText();
this.nonOptimizedBinaryCode = module.emitBinary();
module.optimize();
this.textCode = module.emitText();
this.binaryCode = module.emitBinary();
console.log(`Raw memory code: \n${this.rawMemTextCode}`);
console.log(`Final code: \n${this.textCode}`);
}
catch (e) {
console.log(e);
console.log(`Bad code: \n${module.emitText()}`);
throw e;
}
finally {
rawMemModule.dispose();
module.dispose();
}
}
newModule(withRT) {
const module = new binaryen.Module();
module.setFeatures(module.getFeatures() | binaryen.Features.BulkMemory);
if (withRT) {
rt.addImportsToModule(module);
}
return module;
}
organizeMemory(module, expressions) {
const memoryBuilder = new StaticMemoryBuilder(module);
for (let value of expressions) {
value.memory(memoryBuilder);
}
memoryBuilder.build();
}
declareCycleFunction(module, expressions) {
const exps = [];
exps.push(module.call("enter", [], binaryen.none));
for (let value of expressions) {
exps.push(...value.read(module));
}
for (let value of expressions) {
exps.push(...value.write(module));
}
exps.push(module.call("leave", [], binaryen.none));
module.addFunction("cycle", binaryen.createType([]), binaryen.none, [], module.block("cycle_block", exps, binaryen.none));
module.addFunctionExport("cycle", "cycle");
}
declareExpressionFunctions(module, expressions) {
for (let value of expressions) {
value.functions(module);
const exports = value.exports();
for (let k in exports) {
module.addFunctionExport(exports[k], k);
}
}
}
validate(module) {
if (!module.validate()) {
throw new Error("Web Assembly module validation failed!");
}
}
get rawMem() {
return this.rawMemBinaryCode.buffer;
}
exports(rt) {
const linker = new wa.Linker({
generated: new WebAssembly.Module(this.binaryCode.buffer)
});
return linker.link(rt.instances).generated.exports;
}
}
class StaticMemoryBuilder {
constructor(module) {
this.module = module;
this.offset = 0;
this.segments = [];
this.allocate(4, [0, 0, 0, 0]);
}
declare(vector, initialValue) {
return this.allocate(vector.componentType.sizeInBytes, vector.buffer(initialValue));
}
build() {
this.allocate(8, charCodesOf("STACK..."));
const minPages = (this.offset + 0xFFFF) / 0x10000;
new Uint32Array(this.segments[0].data.buffer)[0] = this.offset;
this.module.setMemory(minPages, 65536, "mem", this.segments);
}
allocate(wordSize, array) {
const alignment = (wordSize - this.offset % wordSize) % wordSize;
const result = this.offset + alignment;
const segment = {
data: new Uint8Array(array),
offset: this.module.i32.const(result),
passive: false
};
this.segments.push(segment);
this.offset = result + segment.data.length;
return result;
}
}
function charCodesOf(stackMarker) {
const stackMarkerArray = [];
for (let i = 0; i < stackMarker.length; i++) {
stackMarkerArray.push(stackMarker.charCodeAt(i));
}
return stackMarkerArray;
}
function flatten(expressions) {
function visit(expression, visited) {
if (!visited.has(expression)) {
visited.add(expression);
for (let exp of expression.subExpressions()) {
visit(exp, visited);
}
}
}
const result = new Set();
for (let exp of expressions) {
visit(exp, result);
}
return [...result];
}
Loading

0 comments on commit 6cee7ca

Please sign in to comment.