@fink/larix
Version:
A parser for generating fink's AST.
643 lines (564 loc) • 14.1 kB
JavaScript
import { _in_ } from "@fink/js-interop/runtime.js";
import { map_ac, filter, reverse } from "@fink/std-lib/iter.js";
export const get_expr_id = expr => {
const {
type,
op,
value,
loc: {
start,
end
}
} = expr;
const loc_str = `${start.line}:${start.column}-${end.line}:${end.column}`;
{
const ˆvalue_1 = expr;
/* istanbul ignore else */
if (ˆvalue_1 != null) {
const {
type: ˆp_3
} = ˆvalue_1;
/* istanbul ignore else */
if (ˆp_3 === `ident`) {
return `${type}:${value}@${loc_str}`;
}
}
/* istanbul ignore else */
if (ˆvalue_1 != null) {
const {
type: ˆp_4,
op: ˆp_5
} = ˆvalue_1;
/* istanbul ignore else */
if (ˆp_4 != null)
/* istanbul ignore else */
if (ˆp_5 != null) {
return `${type}:${op}@${loc_str}`;
}
}
{
return `${type}@${loc_str}`;
}
}
};
export const get_parent = (expr, {
parents
}) => {
// {(get_expr_id expr): parent_expr=false} = parents
const {
[get_expr_id(expr)]: parent_expr
} = parents;
return parent_expr;
};
export const is_parent = (..._args) => {
while (true) {
const [parent, expr, ctx] = _args;
const ˆvalue_6 = expr;
/* istanbul ignore else */
if (ˆvalue_6 === false) {
return false;
}
/* istanbul ignore else */
if (ˆvalue_6 === parent) {
return true;
}
{
{
const next_expr = get_parent(expr, ctx);
_args = [parent, next_expr, ctx];
continue;
}
}
}
};
export const with_analyze = map_ac((item, ˆ_8, ctx = {}) => [item,, ctx]);
export const add_parents = map_ac(([expr, parent], ˆ_9, {
parents = {},
...ctx
}) => {
const expr_id = get_expr_id(expr);
const next_ctx = { ...ctx,
parents: { ...parents,
[expr_id]: parent
}
};
return [[expr, parent],, next_ctx];
});
export const get_scope = (..._args2) => {
while (true) {
const [expr, ctx] = _args2;
const parent = get_parent(expr, ctx);
{
const ˆvalue_10 = parent;
/* istanbul ignore else */
if (ˆvalue_10 != null) {
const {
type: ˆp_12
} = ˆvalue_10;
/* istanbul ignore else */
if (ˆp_12 === `module`) {
return parent;
}
}
/* istanbul ignore else */
if (ˆvalue_10 != null) {
const {
type: ˆp_13,
args: ˆp_14
} = ˆvalue_10;
/* istanbul ignore else */
if (ˆp_13 === `block`)
/* istanbul ignore else */
if (typeof ˆp_14?.[Symbol.iterator] === "function") {
return parent;
}
}
/* istanbul ignore else */
if (ˆvalue_10 != null) {
const {
type: ˆp_15
} = ˆvalue_10;
/* istanbul ignore else */
if (ˆp_15 === `match:expr`) {
return parent;
}
}
{
_args2 = [parent, ctx];
continue;
}
}
}
};
export const may_bind = (..._args3) => {
while (true) {
const [expr, ctx] = _args3;
const parent = get_parent(expr, ctx);
{
const ˆvalue_16 = parent;
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_18,
left: ˆp_19
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_18 === `assign`)
/* istanbul ignore else */
if (ˆp_19 === expr) {
return true;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_20
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_20 === `spread`) {
_args3 = [parent, ctx];
continue;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
op: ˆp_21
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_21 === `await`) {
_args3 = [parent, ctx];
continue;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_22,
right: ˆp_23
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_22 === `rec:kv`)
/* istanbul ignore else */
if (ˆp_23 === expr) {
_args3 = [parent, ctx];
continue;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_24,
left: ˆp_25,
right: ˆp_26
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_24 === `rec:kv`)
/* istanbul ignore else */
if (ˆp_25 === expr)
/* istanbul ignore else */
if (ˆp_26 === false) {
_args3 = [parent, ctx];
continue;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_27,
[`op`]: ˆp_28,
args: ˆp_29
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_27 === `block`)
/* istanbul ignore else */
if (_in_(ˆp_28, [`match`, `pipe`]))
/* istanbul ignore else */
if (_in_(expr, ˆp_29)) {
return false;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_30,
args: ˆp_31
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_30 === `block`)
/* istanbul ignore else */
if (_in_(expr, ˆp_31)) {
return true;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_32,
exprs: ˆp_33
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_32 === `rec`)
/* istanbul ignore else */
if (_in_(expr, ˆp_33)) {
_args3 = [parent, ctx];
continue;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_34,
exprs: ˆp_35
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_34 === `list`)
/* istanbul ignore else */
if (_in_(expr, ˆp_35)) {
_args3 = [parent, ctx];
continue;
}
}
/* istanbul ignore else */
if (ˆvalue_16 != null) {
const {
type: ˆp_36,
exprs: ˆp_37
} = ˆvalue_16;
/* istanbul ignore else */
if (ˆp_36 === `group`)
/* istanbul ignore else */
if (_in_(expr, ˆp_37)) {
_args3 = [parent, ctx];
continue;
}
}
{
return false;
}
}
}
};
export const is_binding_ident = (expr, ctx) => {
const ˆvalue_38 = expr;
/* istanbul ignore else */
if (ˆvalue_38 != null) {
const {
type: ˆp_40
} = ˆvalue_38;
/* istanbul ignore else */
if (ˆp_40 === `ident`) {
return may_bind(expr, ctx);
}
}
{
return false;
}
};
export const has_kv_parent = (..._args4) => {
while (true) {
const [expr, ctx] = _args4;
const parent = get_parent(expr, ctx);
{
const ˆvalue_41 = parent;
/* istanbul ignore else */
if (ˆvalue_41 != null) {
const {
type: ˆp_43,
left: ˆp_44
} = ˆvalue_41;
/* istanbul ignore else */
if (ˆp_43 === `rec:kv`)
/* istanbul ignore else */
if (ˆp_44 === expr) {
return true;
}
}
/* istanbul ignore else */
if (ˆvalue_41 != null) {
const {
type: ˆp_45
} = ˆvalue_41;
/* istanbul ignore else */
if (ˆp_45 === `member`) {
_args4 = [parent, ctx];
continue;
}
}
{
return false;
}
}
}
};
export const is_referencing = (expr, ctx) => {
const ˆvalue_46 = expr;
/* istanbul ignore else */
if (may_bind(ˆvalue_46, ctx)) {
return false;
}
/* istanbul ignore else */
if (ˆvalue_46 != null) {
const {
type: ˆp_48
} = ˆvalue_46;
/* istanbul ignore else */
if (ˆp_48 === `ident`) {
{
const parent = get_parent(expr, ctx);
{
const ˆvalue_49 = parent;
/* istanbul ignore else */
if (ˆvalue_49 != null) {
const {
type: ˆp_51,
left: ˆp_52,
right: ˆp_53
} = ˆvalue_49;
/* istanbul ignore else */
if (ˆp_51 === `rec:kv`)
/* istanbul ignore else */
if (ˆp_52 === expr)
/* istanbul ignore else */
if (ˆp_53 === false) {
return true;
}
}
/* istanbul ignore else */
if (ˆvalue_49 != null) {
const {
type: ˆp_54,
left: ˆp_55
} = ˆvalue_49;
/* istanbul ignore else */
if (ˆp_54 === `rec:kv`)
/* istanbul ignore else */
if (ˆp_55 === expr) {
return false;
}
}
/* istanbul ignore else */
if (ˆvalue_49 != null) {
const {
type: ˆp_56,
right: ˆp_57
} = ˆvalue_49;
/* istanbul ignore else */
if (ˆp_56 === `member`)
/* istanbul ignore else */
if (ˆp_57 === expr) {
return false;
}
}
/* istanbul ignore else */
if (ˆvalue_49 != null) {
const {
type: ˆp_58,
left: ˆp_59
} = ˆvalue_49;
/* istanbul ignore else */
if (ˆp_58 === `member`)
/* istanbul ignore else */
if (ˆp_59 === expr) {
return !has_kv_parent(parent, ctx);
}
}
/* istanbul ignore else */
if (ˆvalue_49 != null) {
const {
type: ˆp_60,
name: ˆp_61,
value: ˆp_62
} = ˆvalue_49;
/* istanbul ignore else */
if (ˆp_60 === `jsx:attr`)
/* istanbul ignore else */
if (ˆp_61 === expr)
/* istanbul ignore else */
if (ˆp_62 !== false) {
return false;
}
}
{
return true;
}
}
}
}
}
{
return false;
}
};
export const find_binding = (expr, ctx) => {
const expr_scope = get_scope(expr, ctx);
const name = expr.value;
let _do_result;
{
let ˆpipe_result_63 = ctx.bindings;
ˆpipe_result_63 = reverse(ˆpipe_result_63);
ˆpipe_result_63 = filter(({
value
}) => name === value)(ˆpipe_result_63);
_do_result = ˆpipe_result_63 = filter(binding_expr => {
const binding_scope = get_scope(binding_expr, ctx);
return is_parent(binding_scope, expr_scope, ctx);
})(ˆpipe_result_63);
}
const [binding = false] = _do_result;
_do_result = undefined;
return binding;
};
export const add_binding = (expr, ctx) => {
const {
bindings = [],
refs = {}
} = ctx;
return { ...ctx,
bindings: [...bindings, expr],
refs: { ...refs,
[get_expr_id(expr)]: []
}
};
};
export const get_refs = (expr, ctx) => {
let _do_result2;
ˆmatch_65: {
const ˆvalue_64 = expr;
/* istanbul ignore else */
if (ˆvalue_64 === false) {
_do_result2 = `unbound`;
break ˆmatch_65;
}
{
_do_result2 = get_expr_id(expr);
break ˆmatch_65;
}
}
const expr_id = _do_result2;
_do_result2 = undefined;
const {
refs: {
[expr_id]: refs = []
}
} = ctx;
return refs;
};
export const add_ref = (expr, ctx) => {
const binding = find_binding(expr, ctx);
let _do_result3;
ˆmatch_67: {
const ˆvalue_66 = binding;
/* istanbul ignore else */
if (ˆvalue_66 === false) {
_do_result3 = `unbound`;
break ˆmatch_67;
}
{
_do_result3 = get_expr_id(binding);
break ˆmatch_67;
}
}
const binding_id = _do_result3;
_do_result3 = undefined;
const refs = get_refs(binding, ctx);
return { ...ctx,
refs: { ...ctx.refs,
[binding_id]: [...refs, expr]
}
};
};
export const add_binding_refs = map_ac(([expr, parent], ˆ_68, ctx) => {
let _do_result4;
ˆmatch_70: {
const ˆvalue_69 = expr;
/* istanbul ignore else */
if (is_referencing(ˆvalue_69, ctx)) {
_do_result4 = add_ref(expr, ctx);
break ˆmatch_70;
}
/* istanbul ignore else */
if (is_binding_ident(ˆvalue_69, ctx)) {
_do_result4 = add_binding(expr, ctx);
break ˆmatch_70;
}
{
_do_result4 = ctx;
break ˆmatch_70;
}
}
const next_ctx = _do_result4;
_do_result4 = undefined;
return [[expr, parent],, next_ctx];
});
export const add_duplicate_bindings = map_ac(([expr, parent], ids = [], ctx) => {
const ˆvalue_71 = expr;
/* istanbul ignore else */
if (is_binding_ident(ˆvalue_71, ctx)) {
{
const scope_id = get_expr_id(get_scope(expr, ctx));
const id = `${scope_id}${expr.name || expr.value}`;
{
const ˆvalue_73 = id;
/* istanbul ignore else */
if (_in_(ˆvalue_73, ids)) {
{
const {
rebindings = []
} = ctx;
const next_ctx = { ...ctx,
rebindings: [...rebindings, expr]
};
return [[expr, parent], ids, next_ctx];
}
}
{
return [[expr, parent], [...ids, id], ctx];
}
}
}
}
{
return [[expr, parent], ids, ctx];
}
});