2e06a9e52d/vm/gonga/ngaro.go
| 36877ecffde0eb92046bc93494abc376bd51d4fa | 2e06a9e52d352e2a3171540c93bc1712ad6b1799 | ||
|---|---|---|---|
20 | machine. | 20 | machine. |
21 | 21 | ||
22 | In addition to normal ngaro features, this Go version | 22 | In addition to normal ngaro features, this Go version |
23 | allows to launch new cores writing 1 to the port 13. The | 23 | adds concurrency, floating point and direct IO support. |
24 | new core will start running the same (shared) image | ||
25 | from the address at the top of the stack. Cores communicate | ||
26 | writing and id to port 1 (to receive) and 2 (to send). To | ||
27 | remove a channel write its id to ports 1 and 2 and wait. | ||
28 | 24 | ||
29 | Some useful words: | 25 | Concurrency vocabulary: |
30 | 26 | ||
31 | : :go ( a- ) 1 13 out wait ; ( start new core with ip set to a ) | 27 | : :go ( a- ) 1 13 out wait ; ( start new core with ip set to a ) |
32 | : go ( "- ) ' :go ; ( parse a word and run it on a new core ) | 28 | : go ( "- ) ' :go ; ( parse a word and run it on a new core ) |
... | ... | ||
34 | : c-> ( x-y ) 1 out wait 1 in ; ( receive y from channel x ) | 30 | : c-> ( x-y ) 1 out wait 1 in ; ( receive y from channel x ) |
35 | : delchan ( x- ) dup 1 out 2 out wait ; ( delete channel ) | 31 | : delchan ( x- ) dup 1 out 2 out wait ; ( delete channel ) |
36 | 32 | ||
37 | Example: | 33 | Floating poing vocabulary: |
34 | |||
35 | -2000 | ||
36 | dup : fpush [ 5 + , ] ; dup : fpop [ 6 + , ] ; | ||
37 | dup : f>jump [ 10 + , ] ; dup : f<jump [ 11 + , ] ; | ||
38 | dup : f!jump [ 12 + , ] ; dup : f=jump [ 13 + , ] ; | ||
39 | dup : f+ [ 16 + , ] ; dup : f- [ 17 + , ] ; | ||
40 | dup : f* [ 18 + , ] ; dup : f/ [ 19 + , ] ; | ||
41 | drop | ||
42 | |||
43 | Direct IO vocabulary: | ||
44 | |||
45 | -1100 dup : >int? ( a-xf ) [ 28 + , ] ; : . ( x- ) [ 29 + , ] ; | ||
46 | -1200 dup : >float? ( a-xf ) [ 28 + , ] ; : f. ( x- ) [ 29 + , ] ; | ||
47 | -1300 dup : <accept ( ca- ) [ 28 + , ] ; : $. ( a- ) [ 29 + , ] ; | ||
48 | |||
49 | Direct IO usage: | ||
50 | |||
51 | : tib<accept ( c- ) | ||
52 | dup 32 = whitespace @ and if drop -1 then tib <accept ; | ||
53 | : (accept) | ||
54 | dup tib<accept | ||
55 | 32 =if ( ugly way to know if this is the listen loop ) | ||
56 | tib >int? if .data rdrop listen ;then drop | ||
57 | tib >float? if .data rdrop listen ;then drop | ||
58 | then ; | ||
59 | ' (accept) is accept | ||
60 | |||
61 | Example of a concurrent program: | ||
38 | 62 | ||
39 | create ch1 ( It is not needed to create channels, but a ) | 63 | create ch1 ( It is not needed to create channels, but a ) |
40 | create ch2 ( good way to get a semi-random new id ) | 64 | create ch2 ( good way to get a semi-random new id ) |
... | ... | ||
53 | 77 | ||
54 | package ngaro | 78 | package ngaro |
55 | 79 | ||
80 | import ( | ||
81 | "fmt" | ||
82 | "strconv" | ||
83 | "unsafe" | ||
84 | ) | ||
85 | |||
56 | const ( | 86 | const ( |
57 | // Instruction set | 87 | // Instruction set |
58 | Nop = iota | 88 | Nop = iota |
... | ... | ||
87 | Out | 117 | Out |
88 | Wait | 118 | Wait |
89 | 119 | ||
120 | FP = -2000 | ||
121 | IOint = -1100 | ||
122 | IOfloat = -1200 | ||
123 | IOstring = -1300 | ||
124 | |||
90 | stackDepth = 100 | 125 | stackDepth = 100 |
91 | chanBuffer = 128 | 126 | chanBuffer = 128 |
92 | nports = 64 | 127 | nports = 64 |
... | ... | ||
96 | img []int | 131 | img []int |
97 | dump string | 132 | dump string |
98 | channel map[int]chan int | 133 | channel map[int]chan int |
99 | Input *Input | 134 | Input *Input |
100 | Output | 135 | Output |
101 | EndOk chan bool | 136 | EndOk chan bool |
102 | } | 137 | } |
103 | 138 | ||
139 | func ftoi(f float) int { return *(*int)(unsafe.Pointer(&f)) } | ||
140 | func itof(i int) float { return *(*float)(unsafe.Pointer(&i)) } | ||
141 | |||
104 | func (vm *NgaroVM) core(ip int) { | 142 | func (vm *NgaroVM) core(ip int) { |
105 | var port [nports]int | 143 | var port [nports]int |
106 | var sp, rsp int | 144 | var sp, rsp int |
... | ... | ||
214 | port[tos] = data[sp-1] | 252 | port[tos] = data[sp-1] |
215 | sp = sp - 2 | 253 | sp = sp - 2 |
216 | case Wait: | 254 | case Wait: |
217 | sp -= vm.wait(&port, tos, sp-2) | 255 | sp -= vm.wait(&port, tos, sp-2, rsp) |
256 | |||
257 | case FP + GtJump: | ||
258 | ip++ | ||
259 | if itof(data[sp-1]) > itof(tos) { | ||
260 | ip = vm.img[ip] - 1 | ||
261 | } | ||
262 | sp = sp - 2 | ||
263 | case FP + LtJump: | ||
264 | ip++ | ||
265 | if itof(data[sp-1]) < itof(tos) { | ||
266 | ip = vm.img[ip] - 1 | ||
267 | } | ||
268 | sp = sp - 2 | ||
269 | case FP + Add: | ||
270 | data[sp-1] = ftoi(itof(data[sp-1]) + itof(tos)) | ||
271 | sp-- | ||
272 | case FP + Sub: | ||
273 | data[sp-1] = ftoi(itof(data[sp-1]) - itof(tos)) | ||
274 | sp-- | ||
275 | case FP + Mul: | ||
276 | data[sp-1] = ftoi(itof(data[sp-1]) * itof(tos)) | ||
277 | sp-- | ||
278 | case FP + Dinod: | ||
279 | data[sp-1] = ftoi(itof(data[sp-1]) / itof(tos)) | ||
280 | sp-- | ||
281 | |||
282 | case IOint + In: | ||
283 | a := readA(vm.img, tos) | ||
284 | sp++ | ||
285 | if i, err := strconv.Atoi(a); err != nil { | ||
286 | data[sp] = 0 | ||
287 | } else { | ||
288 | data[sp-1] = i | ||
289 | data[sp] = -1 | ||
290 | } | ||
291 | case IOint + Out: | ||
292 | fmt.Fprint(vm.Output, tos) | ||
293 | sp-- | ||
294 | case IOfloat + In: | ||
295 | a := readA(vm.img, tos) | ||
296 | sp++ | ||
297 | if f, err := strconv.Atof(a); err != nil { | ||
298 | data[sp] = 0 | ||
299 | } else { | ||
300 | data[sp-1] = ftoi(f) | ||
301 | data[sp] = -1 | ||
302 | } | ||
303 | case IOfloat + Out: | ||
304 | fmt.Fprint(vm.Output, itof(tos)) | ||
305 | sp-- | ||
306 | case IOstring + In: // Accept | ||
307 | var c [1]byte | ||
308 | var cont func() bool | ||
309 | if data[sp-1] == -1 { | ||
310 | cont = func() bool { return c[0] != ' ' && c[0] != '\n' && c[0] != '\t' } | ||
311 | } else { | ||
312 | cont = func() bool { return c[0] != byte(data[sp-1]) } | ||
313 | } | ||
314 | _, err := vm.Input.Read(c[0:]) | ||
315 | // Skip leading white-space | ||
316 | for data[sp-1] == -1 && (c[0] == ' ' || c[0] == '\n' || c[0] == '\t') { | ||
317 | vm.Input.Read(c[0:]) | ||
318 | } | ||
319 | a := tos | ||
320 | for ; err == nil && cont(); _, err = vm.Input.Read(c[0:]) { | ||
321 | vm.img[a] = int(c[0]) | ||
322 | a++ | ||
323 | } | ||
324 | vm.img[a] = 0 | ||
325 | sp -= 2 | ||
326 | case IOstring + Out: | ||
327 | for i := tos; i < len(vm.img); i++ { | ||
328 | if vm.img[i] == 0 { | ||
329 | break | ||
330 | } | ||
331 | fmt.Fprintf(vm.Output, "%c", byte(vm.img[i])) | ||
332 | } | ||
333 | sp-- | ||
334 | |||
218 | default: | 335 | default: |
219 | rsp++ | 336 | rsp++ |
220 | addr[rsp] = ip | 337 | addr[rsp] = ip |
Download diff