X-Git-Url: https://dreyeck.freedombox.rocks/gitweb/idiomatic.git/blobdiff_plain/96f9e23cc6e9201f27fb656588199e234901420e..291e0dae80776eed417ab084896e7fa2390d5387:/index.js?ds=sidebyside diff --git a/index.js b/index.js index b3334a5..9f1a2b7 100644 --- a/index.js +++ b/index.js @@ -1,33 +1,15 @@ -let express = require('express') -let acorn = require('acorn') -let fs = require('fs') -// let fs = require('node:fs/promises'); +const express = require('express') +const acorn = require('acorn') +const fs = require('fs') +const visitor = require('./visitor.js') -let visitor = require('./visitor.js') -let dir = '../wiki-client/lib' -let mods = [] -const app = express() - - -// P A G E S +// P A R S E -app.get('/index', async (req,res,next) => { - console.log(new Date().toLocaleTimeString(), 'index') - const reductions = counter() - fs.readdir(dir, async (err, files) => { - mods = await Promise.all(files.map(load)) - const doit = branch => {reductions.count(branch.type)} - visitor.wander(mods,doit) - const result = ` -

${reductions.size()} non-terminals -
${reductions.total()} reductions -

${reductions.tally() - .map(([k,v]) => `${v} ${link(k)}`) - .join("
")}` - res.send(result); - next() - }) +const dir = '../wiki-client/lib' +const mods = [] +fs.readdir(dir, async (err, files) => { + mods.push(... await Promise.all(files.map(load))) }) async function load(file) { @@ -39,44 +21,113 @@ async function load(file) { }) } -function link(key) { - if(key.match(/^Ident/)) return `${key}` - if(key.match(/^(As|B|L|U).*Ex/)) return `${key}` - if(key.match(/^Lit/)) return `${key}` - return key -} +// P A G E S -app.get('/terminal', (req,res) => { - const lits = counter() - const id = req.query.type - const field = req.query.field - const doit = branch => {if(branch.type==id) lits.count(branch[field])} - visitor.wander(mods,doit) +const style = (title,here='') => ` + +

${title}  ${escape(here)} 
` +const app = express() + +app.get('/index', async (req,res) => { + const reductions = counter() + visitor.walk(mods,branch => + reductions.count(branch.type)) const result = ` -

${lits.size()} uniques -
${lits.total()} total -

${lits.tally() - .map(([k,v]) => `${v} ${escape(k)}`) - .join("
")}` +

${reductions.size()} non-terminals +
${reductions.total()} reductions +

${reductions.tally() + .map(([k,v]) => `
${v}${link(k)}`) + .join("\n")}
` + res.send(style('index')+result); + + function link(key) { + if(key.match(/^Ident/)) return `${key}` + if(key.match(/^(As|B|L|U).*Ex/)) return `${key}` + if(key.match(/^Lit/)) return `${key}` + return key + } +}) + +app.get('/terminal', (req,res) => { + const {type,field} = req.query + const terms = counter() + visitor.walk(mods,branch => { + if(branch.type==type) + terms.count(branch[field])}) + const result = style('terminal',type)+` +

${terms.size()} uniques +
${terms.total()} total +

${terms.tally() + .map(([k,v]) => `
${v}${escape(k)}`) + .join("\n")}
` res.send(result) }) app.get('/usage', (req,res) => { - const type = req.query.type - const field = req.query.field - const key = req.query.key + const {type,field,key,width,depth} = req.query const list = [] - const doit = (branch,stack) => { - if(branch.type==type && branch[field]==key) - list.push(`${stack.at(-1)} ${sxpr(stack[2],3)}` - // `${stack.length} - // ${stack.at(-1)}-${branch.start}-${branch.end} - // (${stack.slice(0,6).map(n => n.end-n.start).join(" ")})` - ) - } - visitor.wander(mods,doit) - res.send(`

${JSON.stringify(req.query,null,2)}
${list.join("
")}`) + const files = counter() + visitor.walk(mods,(branch,stack) => { + if(branch.type==type && branch[field]==key)list.push(` + + ${stack.at(-1)} + ${sxpr(stack[width ?? 2], depth ?? 3)}`)}) + list.sort((a,b) => vis(a)>vis(b) ? 1 : -1) + const q = (id,delta) => Object.entries(req.query) + .map(([k,v]) => k == id ? `${k}=${+v+delta}` : `${k}=${v}`) + .join('&') + const p = id => ` + ` + const m = id => ` − ` + const d = id => `${id} ${p(id)} ${m(id)}` + res.send(style('usage',key)+` +

${files.total()} uses in ${files.size()} files + ${files.tally().map(([k,v]) => `
${v}${k}`).join("\n")}
+

${d('width')} ${d('depth')}
+

${list.join("\n")}
`) +}) + +app.get('/nesting', (req,res) => { + const {file,type,key,start,end} = req.query + const result = [] + visitor.walk(mods,(branch,stack) => { + if(stack.at(-1)==file && branch.type==type && branch.start==start && branch.end==end) { + const path = stack.slice(0,-1).map((n,i) => ` + + ${n.type}: + ${sxpr(n,3,null,stack[i-1])}`).reverse() + const hit = stack[1] + result.push(` +

${path.join("")}

+

${escape(JSON.stringify(hit,omit,2))}
`) + } + }) + res.send(style('nesting',key)+`${result.join("
")}`) +}) + +app.get('/similar', (req,res) => { + const {file,type,key,start,end,nest} = req.query + let nested + visitor.walk(mods,(branch,stack) => { + if(stack.at(-1)==file && branch.type==type && branch.start==start && branch.end==end) + nested = stack[nest]}) + const norm = node => vis(`\n\n\n${sxpr(node,3,null)}`) + const source = (file,node) => mods.find(mod => mod.file == file).text.substring(+node.start,+node.end) + const want = norm(nested) + const result = [] + visitor.walk(mods,(branch,stack) => { + if(norm(branch) == want) + result.push(`
${escape(source(stack.at(-1),branch))}

`)}) + res.send(style('similar',key)+ + `

${want}


` + + result.join("\n") + ) }) @@ -90,6 +141,7 @@ function counter() { counts.set(item, counts.get(item)+1) else counts.set(item,1) + return item }, size() { return counts.size @@ -119,14 +171,14 @@ function escape(text) { function sxpr(obj,deep,key,child) { const hilite = obj===child ? 'class="hi"' : '' - const link = word => obj.type == 'Identifier' ? `${word}` : word + const link = word => obj.type == 'Identifier' ? `${word}` : word if (obj) { if(deep) { const fields = Object.entries(obj) .filter(([k,v]) => !['start','end','raw','computed','optional','kind'].includes(k)) .map(([k,v]) => k=='type' ? abv(v) : - (typeof v == 'string') ? link(expand(v)) : + (typeof v == 'string') ? link(escape(v)) : Array.isArray(v) ? `[${v.map(o => sxpr(o,deep-1,k,child)).join(" ")}]` : sxpr(v, deep-1, k, child)) .join(" ") @@ -149,12 +201,16 @@ function elipsis(obj) { return `(${dots})` } -function expand(text) { - return text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/\*(.+?)\*/g, '$1') -}; +function vis(row) { + return row.split(/\n/)[3].trim() + .replaceAll(/<.*?>/g,'') + .replaceAll(/\.\.+/g,'..') +} + +function query(obj,adj={}) { + return Object.entries(obj) + .map(([k,v]) => k in adj ? `${k}=${adj[k](v)}` : `${k}=${v}`) + .join('&') +} app.listen(1954) \ No newline at end of file