Compare commits

..

4 Commits

Author SHA1 Message Date
Scott Richmond
2686d70a49 change test case 2024-10-18 15:18:56 -04:00
Scott Richmond
e6b2ffe4c9 add ludus-extraction function from svg 2024-09-09 18:23:13 -04:00
Scott Richmond
7285e599c5 0.1.27 2024-08-02 14:56:05 -04:00
Scott Richmond
39984ac537 build 2024-08-02 14:55:46 -04:00
5 changed files with 81 additions and 58 deletions

View File

@ -2,25 +2,29 @@ import init from "./out.mjs"
const mod = await init() const mod = await init()
let result = null let res = null
let code = null let code = null
export function run (source) { export function run (source) {
code = source code = source
const output = mod.ludus(source).value const output = mod.ludus(source).value
result = JSON.parse(output) res = JSON.parse(output)
return result return res
} }
export function stdout () { export function stdout () {
if (!result) return "" if (!res) return ""
return result.io.console.data return res.io.console.data
} }
export function turtle_commands () { export function turtle_commands () {
if (!result) return [] if (!res) return []
return result.io.turtle.data return res.io.turtle.data
}
export function result () {
return res
} }
const turtle_init = { const turtle_init = {
@ -55,6 +59,7 @@ function resolve_color (color) {
if (typeof color === 'string') return colors[color] if (typeof color === 'string') return colors[color]
if (typeof color === 'number') return [color, color, color, 255] if (typeof color === 'number') return [color, color, color, 255]
if (Array.isArray(color)) return color if (Array.isArray(color)) return color
return [0, 0, 0, 255] // default to black?
} }
let background_color = "black" let background_color = "black"
@ -145,27 +150,33 @@ function command_to_state (prev_state, curr_command) {
} }
} }
function are_eq (v1, v2) { function eq_vect (v1, v2) {
const [x1, y1] = v1 const [x1, y1] = v1
const [x2, y2] = v2 const [x2, y2] = v2
return (x1 === x2) && (y1 === y2) return (x1 === x2) && (y1 === y2)
} }
function eq_color (c1, c2) {
if (c1 === c2) return true
const res1 = resolve_color(c1)
const res2 = resolve_color(c2)
for (let i = 0; i < res1.length; ++i) {
if (res1[i] !== res2[i]) return false
}
return true
}
function states_to_call (prev, curr) { function states_to_call (prev, curr) {
const calls = [] const calls = []
// whose state should we use? // whose state should we use?
// pen states will only differ on more than one property // pen states will only differ on more than one property
// if we use `loadstate` // if we use `loadstate`
// my sense is `prev`, but that may change // my sense is `prev`, but that may change
if (prev.pendown && !are_eq(prev.position, curr.position)) { if (prev.pendown && !eq_vect(prev.position, curr.position)) {
calls.push(["line", prev.position[0], prev.position[1], curr.position[0], curr.position[1]]) calls.push(["line", prev.position[0], prev.position[1], curr.position[0], curr.position[1]])
} }
if (curr.pencolor !== prev.pencolor) { if (!eq_color(curr.pencolor, prev.pencolor)) {
if (Array.isArray(curr.pencolor)) { calls.push(["stroke", ...resolve_color(curr.pencolor)])
calls.push(["stroke", ...curr.pencolor])
} else {
calls.push(["stroke", curr.pencolor])
}
} }
if (curr.penwidth !== prev.penwidth) { if (curr.penwidth !== prev.penwidth) {
calls.push(["strokeWeight", curr.penwidth]) calls.push(["strokeWeight", curr.penwidth])
@ -198,12 +209,12 @@ function turn_to_rad (heading) {
} }
function turn_to_deg (heading) { function turn_to_deg (heading) {
return ((heading % 1) * 360) return (heading % 1) * 360
} }
function svg_render_line (prev, curr) { function svg_render_line (prev, curr) {
if (!prev.pendown) return "" if (!prev.pendown) return ""
if (are_eq(prev.position, curr.position)) return "" if (eq_vect(prev.position, curr.position)) return ""
const {position: [x1, y1], pencolor, penwidth} = prev const {position: [x1, y1], pencolor, penwidth} = prev
const {position: [x2, y2]} = curr const {position: [x2, y2]} = curr
const [r, g, b, a] = resolve_color(pencolor) const [r, g, b, a] = resolve_color(pencolor)
@ -221,6 +232,16 @@ function escape_svg (svg) {
.replace(/'/g, "&apos;") .replace(/'/g, "&apos;")
} }
export function extract_ludus (svg) {
const code = svg.split("<ludus>")[1]?.split("</ludus>")[0] ?? ""
return code
.replace(/&amp;/g, "&")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, `"`)
.replace(/&apos;/g, `'`)
}
function svg_render_path (states) { function svg_render_path (states) {
const path = [] const path = []
for (let i = 1; i < states.length; ++i) { for (let i = 1; i < states.length; ++i) {
@ -271,8 +292,9 @@ export function svg (commands) {
const view_height = (maxY - minY) * 1.2 const view_height = (maxY - minY) * 1.2
const margin = Math.max(view_width, view_height) * 0.1 const margin = Math.max(view_width, view_height) * 0.1
const x1 = minX - margin const x1 = minX - margin
const y1 = minY - margin // don't actually need these:
const x2 = maxX + margin // const y1 = minY - margin
// const x2 = maxX + margin
const y2 = maxY + margin const y2 = maxY + margin
const path = svg_render_path(states) const path = svg_render_path(states)
const turtle = svg_render_turtle(states[states.length - 1]) const turtle = svg_render_turtle(states[states.length - 1])

View File

@ -1,6 +1,7 @@
import {run, p5} from "./ludus.mjs" import {run, p5} from "./ludus.mjs"
const code = ` const code = `
print! ("Hello, world!")
pencolor! (colors :white) pencolor! (colors :white)
repeat 10 { repeat 10 {
repeat 4 { repeat 4 {

View File

@ -1,5 +1,5 @@
<?xml version="1.0" standalone="no"?> <?xml version="1.0" standalone="no"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="background-color:rgb(0 0 0); background-opacity: 1" viewBox="-866.0173929338009 -866.0173929337986 1676.1626960009053 1676.162696000903"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="background-color:rgb(0 0 0); background-opacity: 1" viewBox="-866.0173929337993 -866.0173929338016 1676.162696000903 1676.1626960009057">
<g transform="scale(-1, 1) rotate(180)"> <g transform="scale(-1, 1) rotate(180)">
@ -15,76 +15,76 @@
<line x1="293.892626146237" y1="404.50849718747344" x2="698.4011233337105" y2="110.61587104123663" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="293.892626146237" y1="404.50849718747344" x2="698.4011233337105" y2="110.61587104123663" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="698.4011233337105" y1="110.61587104123663" x2="404.50849718747406" y2="-293.89262614623715" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="698.4011233337105" y1="110.61587104123663" x2="404.50849718747384" y2="-293.892626146237" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="404.50849718747406" y1="-293.89262614623715" x2="2.2737367544323206e-13" y2="-7.389644451905042e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="404.50849718747384" y1="-293.892626146237" x2="2.2737367544323206e-13" y2="-2.8421709430404007e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="2.2737367544323206e-13" y1="-7.389644451905042e-13" x2="475.5282581475772" y2="154.50849718747236" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="2.2737367544323206e-13" y1="-2.8421709430404007e-13" x2="475.5282581475771" y2="154.5084971874731" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="475.5282581475772" y1="154.50849718747236" x2="630.0367553350503" y2="-321.01976096010463" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="475.5282581475771" y1="154.5084971874731" x2="630.0367553350503" y2="-321.01976096010384" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="630.0367553350503" y1="-321.01976096010463" x2="154.50849718747332" y2="-475.5282581475778" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="630.0367553350503" y1="-321.01976096010384" x2="154.50849718747332" y2="-475.528258147577" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="154.50849718747332" y1="-475.5282581475778" x2="-7.105427357601002e-13" y2="-1.0800249583553523e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="154.50849718747332" y1="-475.528258147577" x2="-2.842170943040401e-14" y2="-1.1368683772161603e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-7.105427357601002e-13" y1="-1.0800249583553523e-12" x2="475.5282581475759" y2="-154.50849718747529" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-2.842170943040401e-14" y1="-1.1368683772161603e-13" x2="475.5282581475765" y2="-154.5084971874746" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="475.5282581475759" y1="-154.50849718747529" x2="321.0197609601026" y2="-630.0367553350522" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="475.5282581475765" y1="-154.5084971874746" x2="321.01976096010196" y2="-630.0367553350511" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="321.0197609601026" y1="-630.0367553350522" x2="-154.50849718747406" y2="-475.5282581475781" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="321.01976096010196" y1="-630.0367553350511" x2="-154.50849718747457" y2="-475.5282581475766" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-154.50849718747406" y1="-475.5282581475781" x2="8.810729923425242e-13" y2="-1.7053025658242404e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-154.50849718747457" y1="-475.5282581475766" x2="1.1368683772161603e-12" y2="-4.547473508864641e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="8.810729923425242e-13" y1="-1.7053025658242404e-12" x2="293.89262614623715" y2="-404.50849718747565" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="1.1368683772161603e-12" y1="-4.547473508864641e-13" x2="293.8926261462368" y2="-404.5084971874748" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="293.89262614623715" y1="-404.50849718747565" x2="-110.61587104123731" y2="-698.4011233337112" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="293.8926261462368" y1="-404.5084971874748" x2="-110.61587104123754" y2="-698.4011233337105" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-110.61587104123731" y1="-698.4011233337112" x2="-404.5084971874736" y2="-293.8926261462373" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-110.61587104123754" y1="-698.4011233337105" x2="-404.5084971874731" y2="-293.89262614623607" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-404.5084971874736" y1="-293.8926261462373" x2="7.958078640513122e-13" y2="-1.7053025658242404e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-404.5084971874731" y1="-293.89262614623607" x2="1.3642420526593924e-12" y2="-5.115907697472721e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="7.958078640513122e-13" y1="-1.7053025658242404e-12" x2="5.505690139035474e-13" y2="-500.0000000000017" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="1.3642420526593924e-12" y1="-5.115907697472721e-13" x2="1.3948582226380762e-12" y2="-500.0000000000005" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="5.505690139035474e-13" y1="-500.0000000000017" x2="-499.99999999999943" y2="-500.00000000000415" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="1.3948582226380762e-12" y1="-500.0000000000005" x2="-499.9999999999986" y2="-500.00000000000057" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-499.99999999999943" y1="-500.00000000000415" x2="-500.000000000001" y2="-4.149569576838985e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-499.9999999999986" y1="-500.00000000000057" x2="-499.9999999999987" y2="-5.684341886080801e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-500.000000000001" y1="-4.149569576838985e-12" x2="-1.0231815394945443e-12" y2="-3.414781497350573e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-499.9999999999987" y1="-5.684341886080801e-13" x2="1.3073986337985843e-12" y2="-5.684341886080801e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-1.0231815394945443e-12" y1="-3.414781497350573e-12" x2="-293.89262614623624" y2="-404.5084971874781" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="1.3073986337985843e-12" y1="-5.684341886080801e-13" x2="-293.8926261462343" y2="-404.508497187475" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-293.89262614623624" y1="-404.5084971874781" x2="-698.4011233337104" y2="-110.6158710412422" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-293.8926261462343" y1="-404.508497187475" x2="-698.4011233337087" y2="-110.61587104123936" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-698.4011233337104" y1="-110.6158710412422" x2="-404.5084971874767" y2="293.89262614623357" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-698.4011233337087" y1="-110.61587104123936" x2="-404.5084971874733" y2="293.8926261462352" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-404.5084971874767" y1="293.89262614623357" x2="-1.4210854715202004e-12" y2="-8.526512829121202e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-404.5084971874733" y1="293.8926261462352" x2="1.0800249583553523e-12" y2="-4.547473508864641e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-1.4210854715202004e-12" y1="-8.526512829121202e-13" x2="-475.52825814757705" y2="-154.50849718747796" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="1.0800249583553523e-12" y1="-4.547473508864641e-13" x2="-475.528258147575" y2="-154.5084971874763" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-475.52825814757705" y1="-154.50849718747796" x2="-630.0367553350534" y2="321.019760960098" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-475.528258147575" y1="-154.5084971874763" x2="-630.0367553350509" y2="321.0197609600998" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-630.0367553350534" y1="321.019760960098" x2="-154.5084971874772" y2="475.52825814757347" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-630.0367553350509" y1="321.0197609600998" x2="-154.50849718747486" y2="475.52825814757574" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-154.5084971874772" y1="475.52825814757347" x2="8.526512829121202e-13" y2="-1.9326762412674725e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-154.50849718747486" y1="475.52825814757574" x2="9.663381206337363e-13" y2="-3.410605131648481e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="8.526512829121202e-13" y1="-1.9326762412674725e-12" x2="-475.5282581475776" y2="154.50849718746656" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="9.663381206337363e-13" y1="-3.410605131648481e-13" x2="-475.5282581475769" y2="154.50849718747014" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-475.5282581475776" y1="154.50849718746656" x2="-321.01976096010833" y2="630.0367553350447" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-475.5282581475769" y1="154.50849718747014" x2="-321.0197609601066" y2="630.0367553350482" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-321.01976096010833" y1="630.0367553350447" x2="154.50849718746963" y2="475.52825814757466" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-321.0197609601066" y1="630.0367553350482" x2="154.50849718747122" y2="475.5282581475776" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="154.50849718746963" y1="475.52825814757466" x2="-1.3073986337985843e-12" y2="-3.069544618483633e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="154.50849718747122" y1="475.5282581475776" x2="7.105427357601002e-13" y2="-2.2737367544323206e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-1.3073986337985843e-12" y1="-3.069544618483633e-12" x2="-293.89262614624386" y2="404.5084971874663" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="7.105427357601002e-13" y1="-2.2737367544323206e-13" x2="-293.89262614623954" y2="404.5084971874708" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="-293.89262614624386" y1="404.5084971874663" x2="110.615871041226" y2="698.4011233337081" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="-293.89262614623954" y1="404.5084971874708" x2="110.61587104123151" y2="698.401123333711" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="110.615871041226" y1="698.4011233337081" x2="404.5084971874672" y2="293.8926261462378" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="110.61587104123151" y1="698.401123333711" x2="404.5084971874717" y2="293.8926261462399" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<line x1="404.5084971874672" y1="293.8926261462378" x2="-1.5916157281026244e-12" y2="-5.5706550483591855e-12" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/> <line x1="404.5084971874717" y1="293.8926261462399" x2="6.252776074688882e-13" y2="-2.8421709430404007e-13" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1"/>
<g transform="translate(-1.5916157281026244e-12, -5.5706550483591855e-12)rotate(3959.9999999999995)"> <g transform="translate(6.252776074688882e-13, -2.8421709430404007e-13)rotate(359.9999999999994)">
<polygon points="0 20 -13.226237306473037 -15.00222139260919 13.226237306473037 -15.00222139260919" stroke="none" fill="rgb(255 255 255)" fill-opacity="0.5882352941176471"/> <polygon points="0 20 -13.226237306473037 -15.00222139260919 13.226237306473037 -15.00222139260919" stroke="none" fill="rgb(255 255 255)" fill-opacity="0.5882352941176471"/>
<line x1="0" y1="20" x2="0" y2="0" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1" /> <line x1="0" y1="20" x2="0" y2="0" stroke="rgb(255 255 255)" stroke-opacity="1" stroke-width="1" />
</g> </g>

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@ludus/ludus-js-pure", "name": "@ludus/ludus-js-pure",
"version": "0.1.26", "version": "0.1.27",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ludus/ludus-js-pure", "name": "@ludus/ludus-js-pure",
"version": "0.1.26", "version": "0.1.27",
"license": "GPL-3.0", "license": "GPL-3.0",
"devDependencies": { "devDependencies": {
"shadow-cljs": "^2.26.0", "shadow-cljs": "^2.26.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@ludus/ludus-js-pure", "name": "@ludus/ludus-js-pure",
"version": "0.1.26", "version": "0.1.27",
"description": "A Ludus interpreter in a pure JS function.", "description": "A Ludus interpreter in a pure JS function.",
"type": "module", "type": "module",
"main": "build/ludus.mjs", "main": "build/ludus.mjs",