Skip to content

Commit c82fd3a

Browse files
committed
graphics: Initialize graphics primitives
Initialize graphics primitives: move, line, rect, circle, color and width (line width). Refactor DefaultBuiltins() function to take a Runtime struct with graphics primitives provided.
1 parent ee25c0a commit c82fd3a

File tree

7 files changed

+296
-53
lines changed

7 files changed

+296
-53
lines changed

frontend/index.css

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,16 @@ main {
120120
}
121121
.code, .out {
122122
flex: 1;
123-
padding: 12px 16px;
124123
overflow: scroll;
125124
}
126125
.code {
126+
padding: 12px 16px;
127127
border-right: 1px solid var(--primary-color-dimmer);
128128
}
129+
.out {
130+
display: flex;
131+
flex-direction: column;
132+
}
129133
textarea {
130134
font-family: var(--font-family-code);
131135
color: var(--code-color);
@@ -137,6 +141,19 @@ textarea {
137141
border: none;
138142
background: var(--code-background);
139143
resize: none;
144+
outline: none;
145+
}
146+
147+
.output {
148+
padding: 12px 16px;;
149+
}
150+
.canvas {
151+
flex: 0 1 50%;
152+
border-bottom: 1px solid var(--primary-color-dimmer);
153+
}
154+
#canvas {
155+
border-right: 1px solid var(--primary-color-dimmer);
156+
display: none;
140157
}
141158

142159
.confetti {
@@ -176,6 +193,7 @@ textarea {
176193
flex-direction: column;
177194
}
178195
.code {
196+
flex: 0 1 30%;
179197
border-right: none;
180198
border-bottom: 1px solid var(--primary-color-dimmer);
181199
}

frontend/index.html

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@
1313
<header>
1414
<div>
1515
<button id="evaluate" disabled>Run</button>
16-
<button id="tokenize" disabled>Tokenize</button>
17-
<button id="parse" disabled>Parse</button>
16+
<button id="tokenize" disabled class="hidden">Tokenize</button>
17+
<button id="parse" disabled class="hidden">Parse</button>
1818
</div>
1919
<img src="logo.svg" alt="evy logo" height="100%" />
2020
</header>
2121
<main>
2222
<div class="code">
23-
<textarea id="code">
24-
move 10 10
25-
line 20 20
23+
<textarea id="code" spellcheck="false" autocapitalize="none">
24+
move 10 20
25+
line 50 50
26+
rect 25 25
27+
color "lime"
28+
circle 10
2629

2730
x := 12
2831
print "x:" x
@@ -32,7 +35,12 @@
3235
</textarea>
3336
</div>
3437
<div class="out">
35-
<textarea id="output" disabled></textarea>
38+
<div class="canvas">
39+
<canvas id="canvas"></canvas>
40+
</div>
41+
<div class="output">
42+
<textarea id="output" disabled></textarea>
43+
</div>
3644
</div>
3745
</main>
3846
</body>

frontend/index.js

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ function initWasm() {
99
wasm = obj.instance
1010
go.run(wasm)
1111
})
12-
go.importObject.env = { 'main.jsPrint': jsPrint }
12+
go.importObject.env = {
13+
'main.jsPrint': jsPrint,
14+
'main.move': move,
15+
'main.line': line,
16+
'main.width': width,
17+
'main.circle': circle,
18+
'main.rect': rect,
19+
'main.color': color,
20+
}
1321
document.querySelectorAll('header button').forEach((button) => {
1422
button.onclick = handleRun
1523
button.disabled = false
@@ -18,17 +26,22 @@ function initWasm() {
1826
}
1927

2028
// jsPrint converts wasm memory bytes from ptr to ptr+len to string and
21-
// writes it the output pane.
29+
// writes it to the output textarea.
2230
function jsPrint(ptr, len) {
23-
const buf = new Uint8Array(wasm.exports.memory.buffer, ptr, len)
24-
const str = new TextDecoder('utf8').decode(buf)
31+
const s = memString(ptr, len)
2532
const output = document.getElementById('output')
26-
output.textContent += str
27-
if (str.toLowerCase().includes('confetti')) {
33+
output.textContent += s
34+
if (s.toLowerCase().includes('confetti')) {
2835
showConfetti()
2936
}
3037
}
3138

39+
function memString(ptr, len) {
40+
const buf = new Uint8Array(wasm.exports.memory.buffer, ptr, len)
41+
const s = new TextDecoder('utf8').decode(buf)
42+
return s
43+
}
44+
3245
// handleRun retrieves the input string from the code pane and
3346
// converts it to wasm memory bytes. It then calls the evy evaluate
3447
// function.
@@ -39,6 +52,7 @@ function handleRun(event) {
3952
const mem = new Uint8Array(wasm.exports.memory.buffer, ptr, bytes.length)
4053
mem.set(new Uint8Array(bytes))
4154
document.getElementById('output').textContent = ''
55+
resetCanvas()
4256
const fn = wasm.exports[event.target.id] // evaluate, tokenize or parse
4357
fn(ptr, bytes.length)
4458
}
@@ -66,7 +80,7 @@ function showConfetti() {
6680
.sort((a, b) => a.r - b.r)
6781

6882
const cssText = (c) =>
69-
`background: ${c.color};left: ${c.x}%; top: ${c.y}%; transform: scale(${c.r})`
83+
`background: ${c.color}; left: ${c.x}%; top: ${c.y}%; transform: scale(${c.r})`
7084
const confettiDivs = confetti.map((c) => {
7185
const div = document.createElement('div')
7286
div.style.cssText = cssText(c)
@@ -98,3 +112,100 @@ function showConfetti() {
98112
confettiDivs.forEach((div) => div.classList.add('fadeout'))
99113
}, 8500)
100114
}
115+
116+
// graphics
117+
118+
const canvas = {
119+
x:0,
120+
y:0,
121+
ctx: null,
122+
scale: {x: 10, y: -10},
123+
width: 100,
124+
height:100,
125+
126+
offset: {x: 0, y:-100}, // height
127+
}
128+
129+
function scaleX(x) {
130+
return canvas.scale.x * x
131+
}
132+
133+
function scaleY(y) {
134+
return canvas.scale.y * y
135+
}
136+
137+
function transformX(x) {
138+
return scaleX(x + canvas.offset.x)
139+
}
140+
141+
function transformY(y) {
142+
return scaleY(y + canvas.offset.y)
143+
}
144+
145+
function move(x, y) {
146+
canvas.x = transformX(x)
147+
canvas.y = transformY(y)
148+
}
149+
150+
function line(x2, y2) {
151+
console.log("line x:", x2, "y:", y2)
152+
const {ctx, x, y} = canvas
153+
ctx.beginPath()
154+
ctx.moveTo(x, y)
155+
ctx.lineTo(transformX(x2), transformY(y2))
156+
ctx.stroke();
157+
move(x2, y2)
158+
}
159+
160+
function color(ptr, len) {
161+
const s = memString(ptr, len)
162+
console.log("color:", s)
163+
canvas.ctx.fillStyle = s;
164+
canvas.ctx.strokeStyle = s;
165+
}
166+
167+
function width(n) {
168+
console.log("lineWidth:", n)
169+
canvas.ctx.lineWidth = scaleX(n);
170+
}
171+
172+
function rect(dx, dy) {
173+
console.log("rect dx:", dx, "dy:", dy)
174+
const {ctx, x, y} = canvas
175+
const sDX = scaleX(dx)
176+
const sDY = scaleY(dy)
177+
canvas.ctx.fillRect(x, y, sDX, sDY)
178+
canvas.x = x + sDX
179+
canvas.y = y + sDY
180+
}
181+
182+
function circle(r) {
183+
console.log("circle r:", r)
184+
const { x, y, ctx } = canvas
185+
ctx.beginPath()
186+
ctx.arc(x, y, scaleX(r), 0, Math.PI * 2, true)
187+
ctx.fill()
188+
}
189+
190+
function initCanvas() {
191+
const c = document.getElementById("canvas")
192+
const b = c.parentElement.getBoundingClientRect()
193+
const side = b.width < b.height ? b.width : b.height
194+
c.width = Math.abs(scaleX(canvas.width))
195+
c.height = Math.abs(scaleY(canvas.height))
196+
console.log("width", c.width, "height", c.height)
197+
c.style.width = `${side}px`
198+
c.style.display = 'block'
199+
canvas.ctx = c.getContext("2d")
200+
}
201+
202+
function resetCanvas() {
203+
const ctx = canvas.ctx
204+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
205+
ctx.fillStyle = "black"
206+
ctx.strokeStyle = "black"
207+
ctx.lineWidth = 1
208+
move(0,0)
209+
}
210+
211+
initCanvas()

main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ func (c *cmdParse) Run() error {
6464
return err
6565
}
6666
printFunc := func(s string) { fmt.Print(s) }
67-
builtins := evaluator.DefaultBuiltins(printFunc).Decls()
67+
rt := evaluator.Runtime{Print: printFunc}
68+
builtins := evaluator.DefaultBuiltins(rt).Decls()
6869
result := parser.Run(string(b), builtins)
6970
fmt.Println(result)
7071
return nil

0 commit comments

Comments
 (0)