1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# Temperature Converter app
# https://eugenkiss.github.io/7guis/tasks/#temp
#
# To build:
# $ ./translate converter.mu
# To run:
# $ qemu-system-i386 code.img
# todo:
# less duplication
# error checking for input without hard-aborting
fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
# celsius numeric representation
var zero: float
var celsius/xmm1: float <- fahrenheit-to-celsius zero
# celsius string representation
var s-storage: (stream byte 0x10)
var s/ecx: (addr stream byte) <- address s-storage
write-float-decimal-approximate s, celsius, 2/decimal-places
# celsius input/display
var celsius-input-storage: gap-buffer
var celsius-input/esi: (addr gap-buffer) <- address celsius-input-storage
initialize-gap-buffer celsius-input, 8/capacity
load-gap-buffer-from-stream celsius-input, s
var cursor-in-celsius?/edx: boolean <- copy 0xffffffff/true
# fahrenheit numeric representation
var fahrenheit/xmm2: float <- celsius-to-fahrenheit celsius
# fahrenheit string representation
clear-stream s
write-float-decimal-approximate s, fahrenheit, 2/decimal-places
# fahrenheit input/display
var fahrenheit-input-storage: gap-buffer
var fahrenheit-input/edi: (addr gap-buffer) <- address fahrenheit-input-storage
initialize-gap-buffer fahrenheit-input, 8/capacity
load-gap-buffer-from-stream fahrenheit-input, s
var cursor-in-fahrenheit?/ebx: boolean <- copy 0/false # exactly one cursor boolean must be true at any time
# widget title
set-cursor-position screen, 0x1f/x 0xe/y
draw-text-rightward-from-cursor-over-full-screen screen, " Converter ", 0xf/fg 0x16/bg
# event loop
{
# draw current state to screen
clear-rect screen, 0x1f/xmin 0xf/ymin, 0x45/xmax 0x14/ymax, 0xc5/color
var x/eax: int <- render-gap-buffer screen, celsius-input, 0x20/x 0x10/y, cursor-in-celsius?, 7/fg 0/bg
x <- draw-text-rightward screen, " celsius = ", x, 0x45/xmax, 0x10/y, 7/fg 0xc5/bg
x <- render-gap-buffer screen, fahrenheit-input, x 0x10/y, cursor-in-fahrenheit?, 7/fg 0/bg
x <- draw-text-rightward screen, " fahrenheit", x, 0x45/xmax, 0x10/y, 7/fg 0xc5/bg
# render a menu bar
set-cursor-position screen, 0x21/x 0x12/y
draw-text-rightward-from-cursor-over-full-screen screen, " tab ", 0/fg 0x5c/bg=highlight
draw-text-rightward-from-cursor-over-full-screen screen, " switch sides ", 7/fg 0xc5/bg
draw-text-rightward-from-cursor-over-full-screen screen, " enter ", 0/fg 0x5c/bg=highlight
draw-text-rightward-from-cursor-over-full-screen screen, " convert ", 7/fg 0xc5/bg
# process a single keystroke
$main:input: {
var key/eax: byte <- read-key keyboard
var key/eax: grapheme <- copy key
compare key, 0
loop-if-=
# tab = switch cursor between input areas
compare key, 9/tab
{
break-if-!=
cursor-in-celsius? <- not
cursor-in-fahrenheit? <- not
break $main:input
}
# enter = convert in appropriate direction
compare key, 0xa/newline
{
break-if-!=
{
compare cursor-in-celsius?, 0/false
break-if-=
clear-stream s
emit-gap-buffer celsius-input, s
celsius <- parse-float-decimal s
fahrenheit <- celsius-to-fahrenheit celsius
clear-stream s
write-float-decimal-approximate s, fahrenheit, 2/decimal-places
clear-gap-buffer fahrenheit-input
load-gap-buffer-from-stream fahrenheit-input, s
}
{
compare cursor-in-fahrenheit?, 0/false
break-if-=
clear-stream s
emit-gap-buffer fahrenheit-input, s
{
var tmp/xmm1: float <- parse-float-decimal s
fahrenheit <- copy tmp
}
celsius <- fahrenheit-to-celsius fahrenheit
clear-stream s
write-float-decimal-approximate s, celsius, 2/decimal-places
clear-gap-buffer celsius-input
load-gap-buffer-from-stream celsius-input, s
}
break $main:input
}
# otherwise pass key to appropriate input area
compare cursor-in-celsius?, 0/false
{
break-if-=
edit-gap-buffer celsius-input, key
break $main:input
}
compare cursor-in-fahrenheit?, 0/false
{
break-if-=
edit-gap-buffer fahrenheit-input, key
break $main:input
}
}
loop
}
}
fn fahrenheit-to-celsius f: float -> _/xmm1: float {
var result/xmm1: float <- copy f
var thirty-two/eax: int <- copy 0x20
var thirty-two-f/xmm0: float <- convert thirty-two
result <- subtract thirty-two-f
var factor/xmm0: float <- rational 5, 9
result <- multiply factor
return result
}
fn celsius-to-fahrenheit c: float -> _/xmm2: float {
var result/xmm1: float <- copy c
var factor/xmm0: float <- rational 9, 5
result <- multiply factor
var thirty-two/eax: int <- copy 0x20
var thirty-two-f/xmm0: float <- convert thirty-two
result <- add thirty-two-f
return result
}
|