functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
59 lines (58 loc) • 2.54 kB
JavaScript
import { error, ok } from "../../types/result/module.f.js";
import { fold, drop, map as listMap, toArray, includes } from "../../types/list/module.f.js";
import { tokenize } from "../tokenizer/module.f.js";
import { setReplace, at } from "../../types/ordered_map/module.f.js";
import { stringToList } from "../../text/utf16/module.f.js";
import { concat as pathConcat } from "../../path/module.f.js";
import { parseFromTokens } from "../parser/module.f.js";
import { run } from "../ast/module.f.js";
const mapDjs = context => path => {
const res = at(path)(context.complete);
if (res === null) {
throw 'unexpected behaviour';
}
return res.djs;
};
const transpileWithImports = path => parseModuleResult => context => {
if (parseModuleResult[0] === 'ok') {
const dir = pathConcat(path)('..');
const pathsCombine = listMap(pathConcat(dir))(parseModuleResult[1][0]);
const contextWithImports = fold(foldNextModuleOp)({ ...context, stack: { first: path, tail: context.stack } })(pathsCombine);
if (contextWithImports.error !== null) {
return contextWithImports;
}
const args = toArray(listMap(mapDjs(contextWithImports))(pathsCombine));
const djs = { djs: run(parseModuleResult[1][1])(args) };
return { ...contextWithImports, stack: drop(1)(contextWithImports.stack), complete: setReplace(path)(djs)(contextWithImports.complete) };
}
return { ...context, error: parseModuleResult[1] };
};
const parseModule = path => context => {
const content = context.fs.readFileSync(path, 'utf8');
if (content === null) {
return error({ message: 'file not found', metadata: null });
}
const tokens = tokenize(stringToList(content))(path);
return parseFromTokens(tokens);
};
const foldNextModuleOp = path => context => {
if (context.error !== null) {
return context;
}
if (includes(path)(context.stack)) {
return { ...context, error: { message: 'circular dependency', metadata: null } };
}
if (at(path)(context.complete) !== null) {
return context;
}
const parseModuleResult = parseModule(path)(context);
return transpileWithImports(path)(parseModuleResult)(context);
};
export const transpile = fs => path => {
const context = foldNextModuleOp(path)({ fs, stack: null, complete: null, error: null });
if (context.error !== null) {
return error(context.error);
}
const result = at(path)(context.complete)?.djs;
return ok(result);
};