Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:voidlanguage/void into drew/voi-…
Browse files Browse the repository at this point in the history
…16-basic-nominal-object-support
  • Loading branch information
drew-y committed Aug 29, 2024
2 parents 8870e54 + aabcfa1 commit b6cbd91
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 5 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Node.js CI

on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
- run: npm ci
- run: npm run build --if-present
- run: npm test
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"type": "module",
"scripts": {
"test": "node --test **/__tests__/**/*.test.mjs",
"build": "npx tsc",
"prepublishOnly": "tsc"
},
"bin": {
Expand Down
21 changes: 21 additions & 0 deletions src/__tests__/api.test.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, it } from "node:test";
import { e2eVoidText } from "./fixtures/e2e-file.mjs";
import { compileText } from "../api.mjs";
import { strict as assert } from "node:assert";

describe("API: E2E", () => {
it("Can compile and run a basic void file", async () => {
const mod = await compileText(e2eVoidText);
const bin = mod.emitBinary();
const compiled = new WebAssembly.Module(bin);
const instance = new WebAssembly.Instance(compiled);

const fn =
typeof instance.exports.main === "function"
? instance.exports.main
: undefined;

assert(fn, "Function exists");
assert.equal(fn(), 55, "Main function returns correct value");
});
});
13 changes: 13 additions & 0 deletions src/__tests__/fixtures/e2e-file.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const e2eVoidText = `
use std::all
fn fib(n: i32) -> i32
if n < 2 then:
n
else:
fib(n - 1) + fib(n - 2)
pub fn main()
fib(10)
`;
70 changes: 70 additions & 0 deletions src/api.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { ParsedFiles, parseDirectory } from "./lib/parse-directory.mjs";
import { parseFile } from "./lib/parse-file.mjs";
import { parseStd, stdPath } from "./lib/parse-std.mjs";
import { resolveSrc } from "./lib/resolve-src.mjs";
import { File } from "./lib/file.mjs";
import { parse } from "./parser.mjs";
import { expandSyntaxMacrosOfFiles } from "./syntax-macros/index.mjs";
import { resolveFileModules } from "./modules.mjs";
import { expandRegularMacros } from "./regular-macros.mjs";
import { typeCheck } from "./semantics/index.mjs";
import binaryen from "binaryen";
import { genWasmCode } from "./wasm-code-gen.mjs";

export type ParsedModule = {
files: ParsedFiles;
/** Path to src directory (a folder containing index.void that acts as entry) if available */
srcPath?: string;
/** Path to root void file */
indexPath: string;
};

export const compileText = async (text: string) => {
const parsedModule = await parseText(text);
return compileParsedModule(parsedModule);
};

export const compilePath = async (path: string) => {
const parsedModule = await parsePath(path);
return compileParsedModule(parsedModule);
};

export const compileParsedModule = (module: ParsedModule): binaryen.Module => {
const syntaxExpandedFiles = expandSyntaxMacrosOfFiles(module.files);
const moduleResolvedModule = resolveFileModules({
...module,
files: syntaxExpandedFiles,
stdPath: stdPath,
});
const regularMacroExpandedModule = expandRegularMacros(moduleResolvedModule);
const typeCheckedModule = typeCheck(regularMacroExpandedModule);
return genWasmCode(typeCheckedModule);
};

export const parseText = async (text: string): Promise<ParsedModule> => {
const file = new File(text, "index");
return {
files: {
index: parse(file),
...(await parseStd()),
},
indexPath: "index",
};
};

export const parsePath = async (path: string): Promise<ParsedModule> => {
const src = await resolveSrc(path);

const srcFiles = src.srcRootPath
? await parseDirectory(src.srcRootPath)
: { [src.indexPath]: await parseFile(src.indexPath) };

return {
files: {
...srcFiles,
...(await parseStd()),
},
srcPath: src.srcRootPath,
indexPath: src.indexPath,
};
};
1 change: 1 addition & 0 deletions src/wasm-code-gen.mts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const compileExpression = (opts: CompileExprOpts): number => {
if (expr.isType()) return mod.nop();
if (expr.isUse()) return mod.nop();
if (expr.isMacro()) return mod.nop();
if (expr.isMacroVariable()) return mod.nop();

if (expr.isBool()) {
return expr.value ? mod.i32.const(1) : mod.i32.const(0);
Expand Down
12 changes: 7 additions & 5 deletions std/macros.void
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub macro global()
else:
` define_mut_global
`($@function,
$(equals_expr.extract(1))
$(equals_expr.extract(2))
$(equals_expr.extract(1)),
$(equals_expr.extract(2)))

pub macro ';'()
let func = body.extract(0)
Expand Down Expand Up @@ -67,11 +67,13 @@ pub macro fn()
body.slice(type_arrow_index + 2)
else: body.slice(1)

`(define_function,
`(
define_function,
$identifier,
$params,
(return_type $@return_type)
$(`(block).concat(expressions)))
(return_type $@return_type),
$(`(block).concat(expressions))
)

pub macro def_wasm_operator(op, wasm_fn, arg_type, return_type)
let params = `(parameters, left: $arg_type, right: $arg_type)
Expand Down

0 comments on commit b6cbd91

Please sign in to comment.