swapforth

Форк
0
/
nuc.py 
912 строк · 22.7 Кб
1
from __future__ import print_function
2
from __future__ import division
3

4
import sys
5
import getopt
6
import struct
7
from functools import partial
8
import operator
9
import array
10
import copy
11
import time
12
import re
13

14
if sys.version_info[0] < 3:
15
    input = raw_input
16

17
sys.path.append("../shell")
18
import swapforth
19

20
def truth(pred):
21
    return [0, -1][pred]
22

23
def setimmediate(func):
24
    func.is_immediate = True
25
    return func
26

27
def ba(x):
28
    if type(x) == str:
29
        return array.array('B', [ord(c) for c in x])
30
    elif type(x) == bytes:
31
        return array.array('B', x)
32
    else:
33
        return array.array('B', str(x))
34

35
def array2bytes(a):
36
    if hasattr(array.array, 'tostring'):
37
        return a.tostring()
38
    else:
39
        return a.tobytes()
40

41
class ForthException(Exception):
42
    def __init__(self, value):
43
        self.value = value
44

45
class SwapForth:
46

47
    def __init__(self, CELL = 4, ENDIAN = '<'):
48
        self.d = []                 # data stack
49
        self.r = []                 # return stack
50
        self.dict = {}              # the dictionary
51
        self.xts = []               # execution token (xt) table
52
        self.ip = 0                 # instruction pointer for inner interpreter
53
        self.loopC = 0              # loop count
54
        self.loopL = 0              # loop limit
55
        self.leaves = []            # tracking LEAVEs from DO..LOOP
56
        self.ram = array.array('B') # memory
57
        self.out = sys.stdout.write # default console output
58

59
        self.CELL = CELL
60
        self.CSIGN = (256 ** self.CELL) >> 1      # Sign bit mask
61
        self.CMASK = (256 ** self.CELL) - 1       # Cell mask
62
        self.cellfmt = ENDIAN + {2: 'h', 4: 'i', 8: 'q'}[self.CELL]
63

64
        def allot(n, d):
65
            r = partial(self.lit, len(self.ram))
66
            r.__doc__ = d
67
            self.ram.extend([0] * n)
68
            return r
69

70
        self.tib = allot(256, "TIB")
71
        self.sourcea = allot(self.CELL, "SOURCEA")
72
        self.sourcec = allot(self.CELL, "SOURCEC")
73
        self.sourceid = allot(self.CELL, "SOURCEID")
74
        self.to_in = allot(self.CELL, ">IN")
75
        self.base = allot(self.CELL, "BASE")
76
        self.state = allot(self.CELL, "STATE")
77

78
        # Run through own bound methods, adding each to the dict
79
        isforth = re.compile(r"[A-Z0-9<>=\-\[\],@!:;+?/*]+$")
80
        for name in dir(self):
81
            o = getattr(self, name)
82
            if not isforth.match(name) and o.__doc__:
83
                # name was not a valid Forth name; try start of the docstring
84
                name = o.__doc__.split()[0]
85
            if callable(o) and isforth.match(name):
86
                self.dict[name] = o
87

88
        self.DECIMAL()
89

90
    def u32(self, x):
91
        return x & self.CMASK
92

93
    def w32(self, x):
94
        x += self.CSIGN
95
        x &= self.CMASK
96
        x -= self.CSIGN
97
        return x
98

99
    def lit(self, n):
100
        """ push literal N on the stack """
101
        self.d.append(n)
102

103
    def popn(self, n):
104
        r = self.d[-n:]
105
        self.d = self.d[:-n]
106
        return r
107

108
    def q(self, s):
109
        for w in s.split():
110
            if w in self.dict:
111
                self.dict[w]()
112
            else:
113
                self.lit(int(w))
114

115
    def binary(self, op):
116
        b = self.d.pop()
117
        self.d[-1] = self.w32(op(self.d[-1], b))
118

119
    def dpop(self):
120
        r = self.d.pop() << (8 * self.CELL)
121
        r += self.d.pop() & self.CMASK
122
        return r
123

124
    def dlit(self, d):
125
        self.lit(self.w32(d & self.CMASK))
126
        self.lit(self.w32(d >> (8 * self.CELL)))
127

128
    def pops(self):
129
        n = self.d.pop()
130
        a = self.d.pop()
131
        return array2bytes(self.ram[a:a+n]).decode("utf-8")
132

133
    # Start of Forth words
134
    #
135
    # If the word is a legal Python identifier, then
136
    # use that name. Otherwise (e.g. '+') the Forth name is in
137
    # the docstring.
138

139
    def HERE(self):
140
        self.lit(len(self.ram))
141

142
    def THROW(self):
143
        e = self.d.pop()
144
        if e:
145
            raise ForthException(e)
146

147
    def CATCH(self):
148
        self.q('SOURCEA @ SOURCEC @ >IN @')
149
        self.q('SOURCEID @ >R')
150
        source_spec = self.popn(3)
151
        (ds,rs,ip) = (len(self.d) - 1, len(self.r), self.ip)
152
        try:
153
            self.EXECUTE()
154
        except ForthException as e:
155
            if len(self.d) > ds:
156
                self.d = self.d[:ds]
157
            else:
158
                self.d = self.d + [0] * (ds - len(self.d))
159
            self.r = self.r[:rs]
160
            self.ip = ip
161
            self.lit(source_spec[0])
162
            self.lit(source_spec[1])
163
            self.lit(source_spec[2])
164
            self.q('R> SOURCEID !')
165
            self.q('>IN ! SOURCEC ! SOURCEA !')
166
            self.lit(e.value)
167
        else:
168
            self.lit(0)
169

170
    def cell_plus(self):
171
        """ CELL+ """
172
        self.d[-1] += self.CELL
173

174
    def DEPTH(self):
175
        self.lit(len(self.d))
176

177
    def SOURCE(self):
178
        self.sourcea()
179
        self.fetch()
180
        self.sourcec()
181
        self.fetch()
182

183
    def fetch(self):
184
        """ @ """
185
        a = self.d.pop()
186
        self.lit(*struct.unpack(self.cellfmt, self.ram[a:a + self.CELL]))
187

188
    def c_fetch(self):
189
        """ C@ """
190
        a = self.d.pop()
191
        self.lit(self.ram[a])
192

193
    def store(self):
194
        """ ! """
195
        a = self.d.pop()
196
        x = self.d.pop()
197
        self.ram[a:a + self.CELL] = array.array('B', struct.pack(self.cellfmt, x))
198

199
    def c_store(self):
200
        """ C! """
201
        a = self.d.pop()
202
        x = self.d.pop()
203
        self.ram[a] = x & 0xff
204

205
    def comma(self):
206
        """ , """
207
        self.ram.extend(ba(struct.pack(self.cellfmt, self.d.pop())))
208

209
    def c_comma(self):
210
        """ C, """
211
        self.ram.extend([self.d.pop()])
212

213
    def slash_string(self):
214
        """ /STRING """
215
        n = self.d.pop()
216
        self.d[-2] += n
217
        self.d[-1] -= n
218

219
    def PARSE(self):
220
        delim = self.d.pop()
221
        self.q('SOURCE >IN @ /STRING')
222

223
        self.q('OVER >R')
224
        while True:
225
            if self.d[-1] == 0:
226
                break
227
            if (self.ram[self.d[-2]]) == delim:
228
                break
229
            self.lit(1)
230
            self.slash_string()
231

232
        self.q('2DUP 1 MIN + SOURCE DROP - >IN !')
233
        self.q('DROP R> TUCK -')
234

235
    def parse_name(self):
236
        """ PARSE-NAME """
237
        self.q('SOURCE >IN @ /STRING')
238

239
        def skip(pred):
240
            while True:
241
                if self.d[-1] == 0:
242
                    break
243
                if not pred(self.ram[self.d[-2]]):
244
                    break
245
                self.lit(1)
246
                self.slash_string()
247

248
        skip(lambda x: x == 32)
249
        self.q('OVER >R')
250
        skip(lambda x: x != 32)
251

252
        self.q('2DUP 1 MIN + SOURCE DROP - >IN !')
253
        self.q('DROP R> TUCK -')
254

255
    def DUP(self):
256
        self.d.append(self.d[-1])
257

258
    def DROP(self):
259
        self.d.pop()
260

261
    def NIP(self):
262
        self.d.pop(-2)
263

264
    def two_drop(self):
265
        """ 2DROP """
266
        self.d.pop()
267
        self.d.pop()
268

269
    def SWAP(self):
270
        (self.d[-2], self.d[-1]) = (self.d[-1], self.d[-2])
271

272
    def two_swap(self):
273
        """ 2SWAP """
274
        (self.d[-4], self.d[-3], self.d[-2], self.d[-1]) = (self.d[-2], self.d[-1], self.d[-4], self.d[-3])
275

276
    def two_over(self):
277
        """ 2OVER """
278
        self.lit(self.d[-4])
279
        self.lit(self.d[-4])
280

281
    def OVER(self):
282
        self.lit(self.d[-2])
283

284
    def TUCK(self):
285
        self.SWAP()
286
        self.OVER()
287

288
    def two_dup(self):
289
        """ 2DUP """
290
        self.d += self.d[-2:]
291

292
    def to_r(self):
293
        """ >R """
294
        self.r.append(self.d.pop())
295

296
    def r_from(self):
297
        """ R> """
298
        self.d.append(self.r.pop())
299

300
    def r_fetch(self):
301
        """ R@ """
302
        self.d.append(self.r[-1])
303

304
    def n_to_r(self):
305
        """ N>R """
306
        n = self.d.pop()
307
        if n:
308
            self.r += self.d[-n:]
309
            self.d = self.d[:-n]
310
        self.r.append(n)
311

312
    def n_r_from(self):
313
        """ NR> """
314
        n = self.r.pop()
315
        if n:
316
            self.d += self.r[-n:]
317
            self.r = self.r[:-n]
318
        self.lit(n)
319

320
    def plus(self):
321
        """ + """
322
        self.binary(operator.__add__)
323

324
    def minus(self):
325
        """ - """
326
        self.binary(operator.__sub__)
327

328
    def _and(self):
329
        """ AND """
330
        self.binary(operator.__and__)
331

332
    def _or(self):
333
        """ OR """
334
        self.binary(operator.__or__)
335

336
    def _xor(self):
337
        """ XOR """
338
        self.binary(operator.__xor__)
339

340
    def LSHIFT(self):
341
        self.binary(operator.__lshift__)
342

343
    def RSHIFT(self):
344
        self.binary(lambda a, b: (a & self.CMASK) >> b)
345

346
    def two_slash(self):
347
        """ 2/ """
348
        self.d[-1] >>= 1
349

350
    def equal(self):
351
        """ = """
352
        self.binary(lambda a, b: truth(a == b))
353

354
    def less_than(self):
355
        """ < """
356
        self.binary(lambda a, b: truth(a < b))
357

358
    def u_less_than(self):
359
        """ U< """
360
        self.binary(lambda a, b: truth((a & self.CMASK) < (b & self.CMASK)))
361

362
    def NEGATE(self):
363
        self.d[-1] = self.w32(-self.d[-1])
364

365
    def INVERT(self):
366
        self.d[-1] = self.w32(self.d[-1] ^ self.CMASK)
367

368
    def MIN(self):
369
        self.lit(min(self.d.pop(), self.d.pop()))
370

371
    def MAX(self):
372
        self.lit(max(self.d.pop(), self.d.pop()))
373

374
    def dplus(self):
375
        """ D+ """
376
        self.dlit(self.dpop() + self.dpop())
377

378
    def u_m_star(self):
379
        """ UM* """
380
        self.dlit(self.u32(self.d.pop()) * self.u32(self.d.pop()))
381

382
    def star(self):
383
        """ * """
384
        self.binary(operator.__mul__)
385

386
    def u_m_slash_mod(self):
387
        """ UM/MOD """
388
        u1 = self.u32(self.d.pop())
389
        ud = self.dpop() & (65536**self.CELL - 1)
390
        self.lit(self.w32(ud % u1))
391
        self.lit(self.w32(ud // u1))
392

393
    def MS(self):
394
        time.sleep(0.001 * self.d.pop())
395

396
    def EMIT(self):
397
        self.out(chr(self.d.pop()))
398

399
    def CR(self):
400
        self.lit(ord('\n'))
401
        self.EMIT()
402

403
    def SPACE(self):
404
        self.lit(ord(' '))
405
        self.EMIT()
406

407
    def BL(self):
408
        self.lit(ord(' '))
409

410
    def WORDS(self):
411
        self.out(" ".join(self.dict))
412

413
    def xt(self, c):
414
        if not c in self.xts:
415
            self.xts.append(c)
416
        return self.xts.index(c) + 1000
417

418
    def SFIND(self):
419
        (a, n) = self.d[-2:]
420
        s = array2bytes(self.ram[a:a+n]).decode("utf-8").upper()
421
        # print('HERE', s.decode("utf-8"), self.dict)
422
        if s in self.dict:
423
            x = self.dict[s]
424
            self.d[-2] = self.xt(x)
425
            if hasattr(x, 'is_immediate'):
426
                self.d[-1] = 1
427
            else:
428
                self.d[-1] = -1
429
        else:
430
            self.lit(0)
431

432
    def EXECUTE(self):
433
        x = self.d.pop()
434
        self.xts[x - 1000]()
435

436
    @setimmediate
437
    def left_paren(self):
438
        """ [ """
439
        self.lit(0)
440
        self.state()
441
        self.store()
442

443
    def right_paren(self):
444
        """ ] """
445
        self.lit(1)
446
        self.state()
447
        self.store()
448

449
    def inner(self, code):
450
        save = self.ip
451
        self.ip = 0
452
        while self.ip < len(code):
453
            c = code[self.ip]
454
            self.ip += 1
455
            c()
456
        self.ip = save
457

458
    def MARKER(self):
459
        self.parse_name()
460
        name = self.pops().upper()
461
        def restore(here, dict):
462
            del self.ram[here:]
463
            self.dict = dict
464
        self.dict[name] = partial(restore, len(self.ram), copy.copy(self.dict))
465

466
    def mkheader(self):
467
        self.parse_name()
468
        self.code = []
469
        self.defining = self.pops().upper()
470

471
    def colon(self):
472
        """ : """
473
        self.mkheader()
474
        self.right_paren()
475
        def endcolon():
476
            self.lastword = partial(self.inner, self.code)
477
            if self.defining in self.dict:
478
                print('warning: refining %s' % self.defining)
479
            self.dict[self.defining] = self.lastword
480
        self.dosemi = endcolon
481

482
    @setimmediate
483
    def semicolon(self):
484
        """ ; """
485
        self.dosemi()
486
        self.left_paren()
487

488
    @setimmediate
489
    def RECURSE(self):
490
        self.code.append(partial(self.inner, self.code))
491

492
    def noname(self):
493
        """ :NONAME """
494
        self.code = []
495
        self.right_paren()
496
        def endnoname():
497
            self.lit(self.xt(partial(self.inner, self.code)))
498
        self.dosemi = endnoname
499

500
    def IMMEDIATE(self):
501
        setattr(self.lastword, 'is_immediate', True)
502

503
    @setimmediate
504
    def does(self):
505
        """ DOES> """
506
        def dodoes(code):
507
            del self.code[1:]
508
            self.code.append(partial(self.inner, code))
509
        dobody = []
510
        self.code.append(partial(dodoes, dobody))
511
        self.semicolon()
512
        self.right_paren()
513
        self.code = dobody
514
        self.dosemi = lambda: 0
515

516
    def to_body(self):
517
        """ >BODY """
518
        code = self.xts[self.d.pop() - 1000].args[0]
519
        code0 = code[0]
520
        self.inner([code0])
521

522
    def ALLOT(self):
523
        self.ram.extend(ba(chr(0) * self.d.pop()))
524

525
    @setimmediate
526
    def POSTPONE(self):
527
        self.parse_name()
528
        self.SFIND()
529
        if self.d[-1] == 0:
530
            self.DROP()
531
            assert 0, "Bad postpone %s" % self.pops()
532
        if self.d.pop() < 0:
533
            self.LITERAL()
534
            self.lit(self.xt(self.compile_comma))
535
        self.compile_comma()
536

537
    def EXIT(self):
538
        self.ip = 99999999;
539

540
    def ACCEPT(self):
541
        (a, n) = self.popn(2)
542
        s = input()[:n]
543
        ns = len(s)
544
        self.ram[a:a + ns] = s
545
        self.lit(ns)
546

547
    def to_number(self, base = None):
548
        """ >NUMBER """
549
        if base is None:
550
            self.base()
551
            self.fetch()
552
            base = self.d.pop()
553

554
        (a, n) = self.popn(2)
555
        ud2 = self.dpop()
556
        try:
557
            while n:
558
                ud2 = base * ud2 + int(chr(self.ram[a]), base)
559
                a += 1
560
                n -= 1
561
        except ValueError:
562
            pass
563
        self.dlit(ud2)
564
        self.lit(a)
565
        self.lit(n)
566

567
    def DECIMAL(self):
568
        self.lit(10)
569
        self.base()
570
        self.store()
571

572
    def compile_comma(self):
573
        """ COMPILE, """
574
        self.code.append(self.xts[self.d.pop() - 1000])
575

576
    def branch(self, x):
577
        self.ip = x
578

579
    def zbranch(self, x):
580
        if self.d.pop() == 0:
581
            self.ip = x
582

583
    @setimmediate
584
    def BEGIN(self):
585
        self.lit(len(self.code))
586

587
    @setimmediate
588
    def AGAIN(self):
589
        self.code.append(partial(self.branch, self.d.pop()))
590

591
    @setimmediate
592
    def AHEAD(self):
593
        self.lit(len(self.code))
594
        self.code.append(self.branch)
595

596
    @setimmediate
597
    def m_if(self):
598
        """ IF """
599
        self.lit(len(self.code))
600
        self.code.append(self.zbranch)
601

602
    @setimmediate
603
    def THEN(self):
604
        p = self.d.pop()
605
        self.code[p] = partial(self.code[p], len(self.code))
606

607
    @setimmediate
608
    def UNTIL(self):
609
        self.code.append(partial(self.zbranch, self.d.pop()))
610

611
    @setimmediate
612
    def LITERAL(self):
613
        self.code.append(partial(self.lit, self.d.pop()))
614

615
    def dodo(self):
616
        self.r.append(self.loopC)
617
        self.r.append(self.loopL)
618
        self.loopC = self.d.pop()
619
        self.loopL = self.d.pop()
620

621
    def qdodo(self):
622
        self.r.append(self.loopC)
623
        self.r.append(self.loopL)
624
        self.loopC = self.d[-1]
625
        self.loopL = self.d[-2]
626
        self._xor()
627

628
    def doloop(self):
629
        before = self.w32(self.loopC - self.loopL) < 0
630
        inc = self.d.pop()
631
        self.loopC = self.w32(self.loopC + inc)
632
        after = self.w32(self.loopC - self.loopL) < 0
633
        if inc > 0:
634
            finish = before > after
635
        else:
636
            finish = before < after
637
        self.lit(finish)
638

639
    @setimmediate
640
    def DO(self):
641
        self.leaves.append([])
642
        self.code.append(self.dodo)
643
        self.lit(len(self.code))
644

645
    @setimmediate
646
    def LOOP(self):
647
        self.lit(1)
648
        self.LITERAL()
649
        self.plus_loop()
650

651
    @setimmediate
652
    def plus_loop(self):
653
        """ +LOOP """
654
        self.code.append(self.doloop)
655
        self.UNTIL()
656
        leaves = self.leaves.pop()
657
        for p in leaves:
658
            self.code[p] = partial(self.code[p], len(self.code))
659
        self.code.append(self.UNLOOP)
660

661
    @setimmediate
662
    def question_do(self):
663
        """ ?DO """
664
        self.code.append(self.qdodo)
665
        self.leaves.append([len(self.code)])
666
        self.code.append(self.zbranch)
667
        self.lit(len(self.code))
668
        return
669

670
        self.code.append(self.two_dup)
671
        self.code.append(self.equal)
672
        self.leaves.append([len(self.code)])
673
        self.code.append(self.zbranch)
674
        self.code.append(self.dodo)
675
        self.lit(len(self.code))
676

677
    def I(self):
678
        self.lit(self.loopC)
679

680
    def J(self):
681
        self.lit(self.r[-2])
682

683
    def UNLOOP(self):
684
        self.loopL = self.r.pop()
685
        self.loopC = self.r.pop()
686

687
    def QUIT(self):
688
        print('QUIT')
689
        raise swapforth.Bye
690

691
    @setimmediate
692
    def LEAVE(self):
693
        self.leaves[-1].append(len(self.code))
694
        self.code.append(self.branch)
695

696
    def EVALUATE(self):
697
        self.q('SOURCE >R >R >IN @ >R')
698
        self.q('SOURCEID @ >R -1 SOURCEID !')
699
        self.q('SOURCEC ! SOURCEA ! 0 >IN !')
700
        self.interpret()
701
        self.q('R> SOURCEID !')
702
        self.q('R> >IN ! R> SOURCEA ! R> SOURCEC !')
703

704
    def source_id(self):
705
        """ SOURCE-ID """
706
        self.q('SOURCEID @')
707

708
    def interpret(self):
709

710
        def consume1(c):
711
            if self.d[-1] != 0:
712
                r = self.ram[self.d[-2]] == c
713
            else:
714
                r = 0
715
            if r:
716
                self.lit(1)
717
                self.slash_string()
718
            return r
719

720
        def da():
721
            self.two_dup()
722
            was = self.pops()
723

724
            if len(was) == 3 and was[0] == "'" and was[2] == "'":
725
                self.two_drop()
726
                self.lit(ord(was[1]))
727
                self.lit(1)
728
                return
729
            self.dlit(0)
730
            self.two_swap()
731
            if consume1(ord('$')):
732
                base = 16
733
            elif consume1(ord('#')):
734
                base = 10
735
            elif consume1(ord('%')):
736
                base = 2
737
            else:
738
                base = None
739
            neg = consume1(ord('-'))
740
            self.to_number(base)
741
            double = consume1(ord('.'))
742
            if self.d.pop() != 0:
743
                self.lit(-13)
744
                self.THROW()
745
            self.DROP()
746
            if double:
747
                if neg:
748
                    self.q('DNEGATE')
749
                self.lit(2)
750
            else:
751
                self.DROP()
752
                if neg:
753
                    self.NEGATE()
754
                self.lit(1)
755

756
        def doubleAlso():
757
            da()
758
            self.DROP()
759

760
        def doubleAlso_comma():
761
            da()
762
            if self.d.pop() == 2:
763
                self.SWAP()
764
                self.LITERAL()
765
            self.LITERAL()
766
            
767
        while True:
768
            self.parse_name()
769
            if self.d[-1] == 0:
770
                break
771
            self.SFIND()
772
            i = self.d.pop() + 1
773
            self.state()
774
            self.fetch()
775
            i += 3 * self.d.pop()
776
            [ # nonimmediate        number              immediate
777
              # ------------        ------              ---------
778
                self.EXECUTE,       doubleAlso,         self.EXECUTE,   # interpretation
779
                self.compile_comma, doubleAlso_comma,   self.EXECUTE    # compilation
780
            ][i]()
781
        self.two_drop()
782

783
    def REFILL(self):
784
        self.q('SOURCEID @')
785
        if self.d.pop() == 0:
786
            self.tib()
787
            self.lit(256)
788
            self.ACCEPT()
789
            self.q('SOURCEC !')
790
            self.q('TIB SOURCEA !')
791
            self.q('0 >IN !')
792
            self.lit(-1)
793
        else:
794
            self.lit(0)
795

796
    def putcmd(self, cmd):
797
        if cmd.endswith('\r'):
798
            cmd = cmd[:-1]
799
        self.tib()
800
        tib = self.d.pop()
801
        for i,c in enumerate(cmd):
802
            self.ram[tib + i] = ord(c)
803
        self.q('TIB SOURCEA !')
804
        self.lit(len(cmd))
805
        self.q('SOURCEC !')
806
        self.q('0 >IN !')
807

808
import threading
809
try:
810
    import queue
811
except ImportError:
812
    import Queue as queue
813

814
class AsyncSwapForth(SwapForth):
815

816
    def __init__(self, cmdq, ready, *options):
817
        SwapForth.__init__(self, *options)
818
        self.cmdq = cmdq
819
        self.ready = ready
820
        while True:
821
            self.REFILL()
822
            if not self.d.pop():
823
                assert 0, "REFILL failed"
824
            self.lit(self.xt(self.interpret))
825
            self.CATCH()
826
            e = self.d.pop()
827
            if e:
828
                codes = {
829
                    -1  : ": aborted",
830
                    -4  : ": stack underflow",
831
                    -9  : ": invalid memory address",
832
                    -13 : ": undefined word",
833
                    -14 : ": interpreting a compile-only word",
834
                    -28 : ": user interrupt"}
835
                self.out('error: %d%s\n' % (e, codes.get(e, "")))
836
            else:
837
                self.out('  ok\r\n')
838

839
    def ACCEPT(self):
840
        (a, n) = self.popn(2)
841
        self.ready.set()
842
        (self.out, s) = self.cmdq.get()[:n]
843
        ns = len(s)
844
        self.ram[a:a + ns] = ba(s)
845
        self.lit(ns)
846

847
class Tethered(swapforth.TetheredTarget):
848
    def __init__(self, *options):
849
        self.searchpath = ['.']
850
        self.log = open("log", "w")
851
        self.ser = None
852
        self.verbose = False
853
        self.interpreting = False
854

855
        self.ready = threading.Event()
856
        self.cmdq = queue.Queue()
857
        self.t = threading.Thread(target = AsyncSwapForth, args = (self.cmdq, self.ready) + options)
858
        self.t.setDaemon(True)
859
        self.t.start()
860
        self.ready.wait()
861

862
    def issue(self, writer, cmd):
863
        assert self.ready.is_set()
864
        self.ready.clear()
865
        self.cmdq.put((writer, cmd))
866
        self.ready.wait()
867

868
    def interactive_command(self, cmd):
869
        self.issue(sys.stdout.write, cmd)
870

871
    def command_response(self, cmd):
872
        r = []
873
        self.issue(lambda c: r.append(c), cmd)
874
        return "".join(r)
875

876
if __name__ == '__main__':
877

878
    cellsize = 4
879
    endian = '<'
880

881
    try:
882
        options,args = getopt.getopt(sys.argv[1:], 'c:b')
883
        optdict = dict(options)
884
        if '-c' in optdict:
885
            cellsize = int(optdict['-c'])
886
        if '-b' in optdict:
887
            endian = '>'
888
    except getopt.GetoptError:
889
        print("usage:")
890
        print(" -c N    cell size, one of 2,4 or 8")
891
        print(" -b      big-endian. Default is little-endian")
892
        sys.exit(1)
893

894
    dpans = {}
895
    allw = set()
896

897
    t = Tethered(cellsize, endian)
898
    t.searchpath += ['../anstests', '../common']
899
    # print set(t.sf.dict.keys()) - dpans['CORE'] 
900

901
    try:
902
        t.include('swapforth.fs')
903
        [t.include(a) for a in args]
904
    except swapforth.Bye:
905
        pass
906
    if 0:
907
        words = set(t.command_response('words').split())
908
        missing = dpans['CORE'] - words
909
        print(len(missing), "MISSING CORE", " ".join(sorted(missing)))
910
        print(words - allw)
911

912
    t.shell()
913

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.