UNPKG

@fink/larix

Version:

A parser for generating fink's AST.

643 lines (564 loc) 14.1 kB
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]; } });