-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlog.txt
4193 lines (3943 loc) · 231 KB
/
log.txt
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
peforth
[x] 13:59 2017-07-31 找到 JavaScript eval() equivalent in Python
https://stackoverflow.com/questions/701802/how-do-i-execute-a-string-containing-python-code-in-python
成功了!!
>>> mycode = 'print ("hello world")'
>>> exec(mycode)
hello world
>>>
The technique of returning a function from another function is known as currying:
https://stackoverflow.com/questions/14261474/how-do-i-write-a-function-that-returns-another-function
Python annoymous function lambda
http://blog.csdn.net/majianfei1023/article/details/45269343
https://www.zhihu.com/question/20125256
[x] review project-k , should project-k support python too?
which will be peforth.py 10:04 2019/11/26 it's projectk.py now.
[x] 直接問 pyforth 的原作者的版權條件 ---> 用不著了.
[x] 實驗用 exec() 生成一個 function
s = '''
def show(s):
print(s)
'''
exec(s)
>>> show('abc')
abc
>>> 成功了!
[x] Try to define an python object
s = '''
class a():
vm = None
def b(self): # self is must
print(b) # b unknown
print(self)
print(a)
vm = self
c = a()
'''
exec(s)
[x] peforth 可以引用的讀檔範例
# average5 .py
def main() :
fileName = input ("What file are the numbers in? " )
infile = open (fileName, ' r ')
sum = 0
count = 0
for line in infile:
sum = sum + eval (line)
count = count + 1
print ("\nThe average Of the numbers is", sum / count)
main ( )
# average6.py
def main() :
fileName = input ("What file are the numbers in? " )
infile = open ( fileName
sum = 0.0
count = 0
line = infile.readline()
while line != ""
sum = sum + eval(line)
count = count + 1
line = infile.readline()
print("\nThe average Of the numbers is", sum / count)
main()
[x] module 的用法搞懂了,很簡單。 peforth.py 就是 peforth VM.
不需要像 javascript 用一個 function 把整個 vm 包起來, see
GitHub\peforth\projectile.py
python can redefine functions and methods. Function and methods are
variables too.
python objects, like javascript, can add properties and methods
through simply assign a value to it.
>>> type(show) # show is an object
<class 'projectile.Projectile'>
>>> show
<projectile.Projectile object at 0x000001C6260D0438>
>>> show.x = 0 # assign new property to show
>>> show.y = 11
>>> show.p = 22
>>> dir(show) # check it out
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'getHere', 'getX', 'getY', 'p',
'update', 'x', 'xpos', 'xvel', 'y', 'ypos', 'yvel']
>>>
[x] python 也可以 see function 的 source code
https://stackoverflow.com/questions/427453/how-can-i-get-the-source-code-of-a-python-function
def foo(a):
x = 2 # how about a comment?
return x + a
import inspect
# inspect.getsource(foo)
# u'def foo(a):\n x = 2\n return x + a\n'
print (inspect.getsource(foo))
==> 結果完全成功, 連 comment 也被顯示出來。
==> 但是 py> py: 組合出來的 function 不行
py> tick('test').cfa ==> 1
py> dictionary[1:] ==> [.s, <function <lambda> at 0x0000024CE15810D0>,
.s, <function <lambda> at 0x0000024CE1581158>, .s, None, None]
OK py> inspect.getsource(dictionary[2]) .
could not get source code <------------------- error message
Debug? [y/N]
同一篇 stackoverflow 介紹的 dis module 也真的可行!
>>> import dis
>>> def func(x):
... print(x+1)
...
>>> func(123)
124
>>> dis.dis(func)
2 0 LOAD_GLOBAL 0 (print)
2 LOAD_FAST 0 (x)
4 LOAD_CONST 1 (1)
6 BINARY_ADD
8 CALL_FUNCTION 1
10 POP_TOP
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
>>> 哇! 顯示出 function 的機械碼, 太正點了!!
[x] Python equivalent of:
Word.prototype.toString = function(){return this.name + " " + this.help}; // every word introduces itself
--> 有了, 就是去定義 __str__ prototype of the class
#------- ex2.py ---------------
class d():
def __str__(self):
return "a __str__"
def __repr__(self):
return "a __repr__"
class x():
name = 'stella'
feet = 'splender'
#------------------------------
>>> import ex2
>>> x = ex2.x()
>>> x
<ex2.x object at 0x00000170D77202B0> <---- default __repr__ 打印
>>> print(x)
<ex2.x object at 0x00000170D77202B0> <---- default __str__ 傳回值
>>> d = ex2.d()
>>> d # <--------- 執行該 obj 時, 打印 __repr__() 的傳回值
a __repr__ # 應該讓它執行該 word
>>> print(d) # <---- obj 本身的傳回值是 __str__() 的傳回值
a __str__
>>>
[x] 進一步刺探未來的 peforth.py kernel module 的特性
Ynote: 搞懂 python 的 module files globals() locals().note
[x] docode() 要組裝 function 需參考 anonymous function 的定義方法:
https://stackoverflow.com/questions/6629876/how-to-make-an-anonymous-function-in-python-without-christening-it
Study built-in function exec() https://docs.python.org/3/library/functions.html#exec
Study build-in function compile() https://docs.python.org/3/library/functions.html#compile
[x] genxt() 成功了
[x] IDLE path working directory working folder
import sys
sys.path.append('c:/Users/hcche/Documents/GitHub/peforth')
20:32 2021/04/10 python 的標準方法用來 import 本機遠處的 module. 我做 Einstein's problems 時的例子:
# 把本機提供 GA 的 directory 增加到 path 裡去,真的就成功了!
!cd --> C:\Users\User\Documents\GitHub\Einstein-s-Problem # 目前的 working directory. 注意,以下用到的東西都在這個 directory 底下一層的 sub-directory 裡。
import sys
sys.path.append(r'c:\Users\User\Documents\GitHub\genetic-algorithms') # 讓 python 找得到 Kei Codes 的 repo
from problems import knapsack # 從 GitHub\genetic-algorithms\problems 裡 imort 到 knapsack.js
from algorithms import bruteforce, genetic # 從 GitHub\genetic-algorithms\algorithms 裡 imort 到 bruteforce.js 與 genetic.js
from utils.analyze import timer # 從 GitHub\genetic-algorithms\utils 裡 imort 到 analyze.js 裡的 timer() function.
[x] 12:50 2017/08/12 已經跑起來了, debugging compiling == 'code' 的問題
--> 可能是 end-code 裡面 Word(newname,newxt) 失敗的關係 --> no, it can't fail
--> 應該是 docode 裡面, 結構不太好, 萬一 reDef 或 genxt() 失敗了會怎樣?
很多都會半途結束, 留下 compiling == 'code' 的問題。 --> all tested, behavior acceptable now
[x] "import re" in peforth.py kernel is not a good choice.
Simply letting the main program to do that. The main program is eforth.3py
--> Yeah! it works.
c:\Users\hcche\Documents\GitHub\peforth>python eforth.3py
hello eforth!!
--> 錯了, 每個 .py 檔都自己 import re, import pdb 反而是對的, see:
https://stackoverflow.com/questions/8957859/python-child-cannot-use-a-module-the-parent-imported
... Generally if you're doing simple obvious things like importing a standard module,
you should do it the simple and obvious way......
[x] reproduce the problem:
import peforth as vm
vm.dictate('code test end-code') # Try this first
vm.words['forth']
這樣是成功的,但是進入 forth command line 之後, 同樣的工作... 還是成功的。
--> 改試 vm.dictate('code test3 print("hello test3!!") end-code')
>>> vm.execute('test3') --> hello test3!! 很成功
--> 進 forth command line
>>> vm.peforth()
OK code test4 print("hello test4") end-code
OK test4
hello test4
OK
還是很成功
--> 好像要出過 error e.g. word unknown 之類才能複製問題
>>> code test5 end-code
File "<stdin>", line 1
code test5 end-code
^
SyntaxError: invalid syntax
>>>
的確是這樣!!! now I've got the SRP
--> 似乎是 w.xt(w) 執行 end-code 時出問題, 檢查此時的 end-code
RI, outer() 裡面分辨 token 是否 [int, float] 用 eval(token) 會有 exception
必須要用 try - except 處理才行。 --> Fixed !!!
[x] why after OK type 'words' no response <--- should be : Error! words unknown.
--> 結果發現, 所有的 dir(vm) attributes 都這樣!!
(Pdb) eval('pop') ==> <function pop at 0x00000178A534A730>
(Pdb) eval('dictionary') ==> [0]
(Pdb) eval('stack') ==> [{'forth': [0, code, end-code, //, stop, *debug*]}, {'forth': [0, code, end-code, //, stop, *debug*]}, {'forth': [0, code, end-code, //, stop, *debug*]}, <class 'peforth.Word'>, <function phaseA at 0x00000178A534A0D0>, <function phaseB at 0x00000178A534A158>]
所以, outer() 還要再改良。
--> eval() 的結果 + 0 就可以保證他是 number 了
[x] kernel project-k.py instead of peforth.py
[X] code word's help, not easy, keep the record.
# stack diagram
ntibwas, s = ntib, nextstring("\\(")
if s['flag']: # stack diagram is existing
pdb.set_trace()
newhelp = '( ' + nexttoken('\\)') + nexttoken() + ' '
else: # return s to tib
ntib = ntibwas
# word description
ntibwas, s = ntib, nextstring("\\")
if s['flag']: # description is existing
newhelp += nexttoken('\n|\r')
else: # return s to tib
ntib = ntibwas
code \ last().help += nexttoken('\n|\r'); end-code immediate
// ( <comment> -- ) Give help message to the new word.
code ( last().help = '( ' + nexttoken('\\)') + nexttoken() + ' ' end-code immediate
// ( -- ) Get stack diagram to the last's help.
--> v1.23 code words 可以用 # 下 help 了。
[x] In jeforth, window.colonxt is dynamicly created by definition of ':'.
Can peforth.f do that too in python? Yes!!!
>>> def test():
... globals()['cc'] = 123
...
>>> cc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'cc' is not defined
>>> test()
>>> cc
123
>>>
[/] : test ;
'module' object does not support item assignment
Debug? [y/N] y
RI: last().xt = xt # also vm['colonxt'] <------ [/] easy, deal with this later
[x] After the above error probably, after colon definition the compiling is still True!!!
--> because forgot declare it a global.
B i n g o ! ! colon definition works now
[x] literal needs to use closure
def gen(n): # function generator
def f(): # literal run time function
print(n)
f.description = "{} {}".format(type(n),n)
return f
f = gen([11,22,33])
f()
>>> f.description
"<class 'list'> [11, 22, 33]"
# functions are not shown by __str__ and __repr__ like dict
# def str(self): # return help message
# return f.description
# def repr(self): # execute xt and return help message
# return f.description
# str.desc = "I am str"
# repr.desc = "I am repr"
# f.__str__ = str
# f.__repr__ = repr
[x] py> py: 都應該改用 compile(code,"")
compile CN http://www.th7.cn/Program/Python/201608/923063.shtml
用到 lambda 就不能用來【賦值】, 安全理由. 故 py: 不能用 lambda. 要的話就必須用 compile 的。
https://stackoverflow.com/questions/20695745/why-use-lambdas-vs-1-line-function-declarations
--> [x] 已經發現 py: tick('//').immediate=True 行不通了!!!
--> 用 <py> </py> </pyV> 分別改寫了 py: py> , ok now
[x] pyExec pyEval 是多餘的 --> 去除
[x] (Pdb) execute("sdfsdf")
(Pdb)
沒半點錯誤訊息, 有問題看不出來!!
--> fixed, now it's a panic.
[x] compiling 未定義怎麼不觸發 unknown?
--> outer() 用 eval(token) 想判斷 token 是否 number 不行,
當 token='compiling' 時不會觸發 exception 反而傳回其值 True or False !!
--> 改用 complex(token) 很完美!
[x] t> >t t@
>>> line = 'Cats are smarter than dogs\n\\ 1234\n\\ 2233'
>>> matchObj = re.search( r'\n\\ (\d*)$', line)
>>> matchObj.group()
'\n\\ 2233'
>>> matchObj.group(1)
'2233'
>>> len(matchObj.group())
7
>>> line[:-7]
'Cats are smarter than dogs\n\\ 1234'
>>>
[x] [/py] [/pyV] 只分別取得 exec-code 與 eval-code 不執行, 可以用 execute 執行嗎?
[x] execute 也要能執行 exec-code 或 eval-code ---> done
[x] 這兩個都不要,應該是個 compyle ( 'source' -- code object ) \ python compiler 指令
[x] 讓 execute() 認得 code object
--> OK ' compyle .
compyle ( "source" -- exec-code ) Python compile source to exec-code object __str__ OK
OK char print('hi') compyle
OK execute
hi
OK 一次就成功了!!
[x] colon definition 裡看能不能用 comma 塞入一個 code object ?
--> : test char print('hi') compyle execute ; 成功
: test2 [ char print('hi') compyle , ] ; 也成功
: cfa ' py> dictionary[pop().cfa:] . cr ;
OK cfa test2
[ /* test2 */ <code object <module> at 0x0000019B24E1F8A0, file "", line 1>, None,
/* cfa */ ', <function xt.<locals>.<lambda> at 0x0000019B24E29C80>, ., cr, None,
None]
OK
[x] 有了 compyle 要不要改寫 <py> </py> </pyV> 等?
--> 只簡化了 </py> 一點點
[x] debug :: --> root cause 又是 branch 裡 assignment to ip 忘了加 vm.ip
OK 11 22 ' + :: xt() .s ==> [33] OK 表示 :: interpret mode 功能 ok
OK : test :: xt() ;
--Return--
> <string>(2)xt()->None
(Pdb) c
OK see-cfa test
[<code object <module> at 0x000001F1364F68A0, file "", line 1>, None, None]
OK 22 33 ' + test
OK .s
[55]
OK
[x] constant 要用到 vm.forth['varname'] 複習一下 python 語法
constant 要做的事 --> 'push(vm["forth"]["x"])'
一開始 word-list 都沒有自己的空間
(Pdb) vm['forth']
*** TypeError: 'module' object is not subscriptable
(Pdb) vm.forth
*** AttributeError: module 'projectk' has no attribute 'forth'
不能這樣 init :
(Pdb) vm['forth']={}
*** TypeError: 'module' object does not support item assignment
要這樣 init :
(Pdb) setattr(vm,'forth',{})
Object 的 attribute 不能這樣 access :
(Pdb) vm['forth'] <--- 這是 dict 的方式
*** TypeError: 'module' object is not subscriptable
要這樣 access :
(Pdb) vm.forth
{}
(Pdb) getattr(vm,'forth')
{}
(Pdb)
[x] colon definition 失敗還是會佔一個位置
OK 123 constant x
OK 345 to x
Error! Assigning to a none-value.
Debug? [y/N]
OK : test 44445555 to x ;
Error! Assigning to a none-value. <--- 馬上觸發錯誤,好。
Debug? [y/N]
OK words
0 code end-code // ...snip... to x test <--- test 佔了位置
OK : ttt ;
OK words
0 code end-code // ...snip... to x test ttt <--- 確實佔了位置
OK test
Error! test unknown. <---- colon definition 失敗, 只是沒有 reveal 而已
Debug? [y/N]
OK rescan-word-hash <---- rescan 之後它就會出現!!
OK test
OK .s
[44445555]
OK
--> jeforth 也一樣, 算了, 有警告就可以了。
--> (forget) 一下可以把它消除掉
[x] tib 平時有被 corrupted
OK char $ . rewind
OK 11 22 33 *debug* # <---- 最簡單的
(Pdb) tib
'112233*debug*' # <----- 就已經有問題了 !!!
(Pdb)
問題在 kernel nexttoken() 裡面
--> Root cause 1 : nexttoken() <--- skip leading white spaces 改寫
Root cause 2 : tib and ntib are strange <-- ntib 太大先排除
[x] writeTextFile 實驗
OK <py> open("pathname.txt", "wt")</pyV> constant f
reDef f
OK f .
<_io.TextIOWrapper name='pathname.txt' mode='wt' encoding='cp950'> OK f :> name
--> pathname.txt OK
OK f :: write("abc")
OK f :: write("123")
OK f :: write("中文")
OK f :: close()
encoding='utf-8'
[x] refill works now. Use refill to improve <text> first. Let it accept
multiple lines. ---> 最後是簡單地引進 accept2 用 Ctrl-D 切換 multiple-line mode 即可. 保留以下研究過程。
: <text>.interpret ( <multi-lines> -- "string" ) // get multi-lines string from ternimal
CR word ( s )
begin
accept if ( s line )
\ get string to s, leave </text> and the rests in tib by adjusting ntib
py> re.search("(.*)</text>(.*)",tos()) ( s line re )
py> bool(tos()) if \ line has </text> ?
( s line re )
py: vm.tib="</text>"+tos().group(2);vm.ntib=0;
\ s += re.group(1)
nip ( s re ) :> group(1) + ( s )
exit
else ( s line re )
\ s += line
drop + ( s )
else ( s )
\ s += '\n'
py> pop()+'\n'
then
refill
again ;
我發現, bool(regEx) 可以看出 re.search 的結果是否 found
[x] See MetaMoji 討論如何適當分割以上複雜的 <text>.interpret 成簡單的 一行成功; 多行輸入 兩段。
其中多行輸入是個公用 routine
[x] 實驗後綴法是否有簡化功效? 使 group(1) 成為共同的結果
\ regular expression 實例
OK <py> re.search("(.*?)</text>(.*)","aa </text>bb</text>")</pyV> ( re ) constant re
OK re bool . cr ^^^^^^ 故意加上後綴讓 re.search 總是成功
True <--- 總是成功
OK re :> group() . cr
aa </text>bb</text>
OK re :> group(1) . cr
aa <----------------------------- group(1) 為所求
OK re :> group(2) . cr
bb</text> <-------------------- group(2) 去掉後綴之後還給 tib
OK <py> re.search("(.*?)</text>(.*)","aa bb</text>")</pyV> ( re ) constant re
OK re bool . cr
True
OK re :> group() . cr
aa bb</text>
OK re :> group(1) . cr
aa bb <------------ 當 bool group(2) False 時 group(1) 仍為所求, 故確有簡化功效
OK re :> group(2) . cr
OK re :> group(2)=="" . cr
True
OK re :> group(2) bool .
False OK
[x] 多行輸入公用 routine
[x] 19:46 2020/10/04 複習需要 ^D 多行輸入 multiple lines inpue 的原因:如果是 colon definition 本來
就可以在 compiling state 多行輸入,問題出在 code ... end-code 期間需要 ^D multiple lines input.
: accepts ( "deli" <multiple lines> -- "string" ) // Get multiple lines from tib up to delimiter
( deli )
begin
accept if ( s line )
\ get string to s, leave </text> and the rests in tib by adjusting ntib
py> re.search("(.*)</text>(.*)",tos()) ( s line re )
py> bool(tos()) if \ line has </text> ?
( s line re )
py: vm.tib="</text>"+tos().group(2);vm.ntib=0;
\ s += re.group(1)
nip ( s re ) :> group(1) + ( s )
exit
else ( s line re )
\ s += line
drop + ( s )
else ( s )
\ s += '\n'
py> pop()+'\n'
then
refill
again ;
code accept2 # use Ctrl-D at the end to terminate the input. py> chr(4)=='^D' --> True
result, s = "", input()
while not chr(4) in s:
result += s
s = input()
result += s.replace(chr(4),'\n') # all ^D become \n
push(result)
push(True)
end-code // ( -- str T|F ) Read a line from terminal.
[x] accept can be single line accept1 or multiple lines accept2 , switch by Ctrl-D
8: [EOT] (<class 'str'>) <---- the Ctrl-D from input()
OK py> ord(tos()[0]) . cr
4
OK
示範 <accept> ... </accept> 的用法
------- clipboard ---------
dropall
<accept>
11
22
33
44
55
</accept>
66
77
88
99
----------------------------
OK dropall # paste 之後的樣子
OK <accept>
11
22
33
44
55
</accept>66 # 這是最後一行,注意!66 可以往前緊貼, delimiter 會整個被忽略掉。
OK 77
OK 88
OK 99
----------------------------
OK .s # 看看結果 .......
0: 11
22
33
44
55
66
(<class 'str'>)
1: True (<class 'bool'>)
2: 77 4Dh (<class 'int'>)
3: 88 58h (<class 'int'>)
4: 99 63h (<class 'int'>)
OK
[x] .s in trouble when cell is False, None ... etc
[x] peforth.py 可以直接執行 : python peforth.py
也可以由 python interpreter 執行: >>> peforth.main() 此時 exit 回到 python interpreter
bye 則會傳回 errorlevel 回到 DOS.
# 從 python interpreter 就可以看到 peforth.py module 裡的 globals
>>> dir(peforth)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
'__package__', '__spec__', 'greeting', 'main', 'panic', 'readTextFile',
'vm', 'writeTextFile']
# 從 python interpreter 更可以看到 project-k vm 裡的 globals
>>> dir(peforth.vm)
['EXIT', 'RET', 'Word', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'code', 'colonxt', 'comma', 'compiling', 'context',
'context_word_list', 'current', 'current_word_list', 'debug', 'dictate', 'dictionary',
'dis', 'docode', 'doendcode', 'endcode', 'execute', 'forth', 'genxt', 'greeting',
'here', 'inner', 'inspect', 'ip', 'isReDef', 'json', 'last', 'major_version', 'multiple',
'name', 'newhelp', 'newname', 'newxt', 'nextstring', 'nexttoken', 'ntib', 'order', 'os',
'outer', 'panic', 'pdb', 'phaseA', 'phaseB', 'pop', 'push', 're', 'readTextFile', 'reset',
'rstack', 'rtos', 'stack', 'stop', 'tib', 'tick', 'tos', 'version', 'vm', 'vocs', 'wordhash',
'words', 'writeTextFile']
# 從 python interpreter 也可以執行 peforth
>>> peforth.vm.dictate
<function dictate at 0x000001D1368E2510>
>>> peforth.vm.dictate('version')
p e f o r t h v1.01
source code http://github.com/hcchengithub/peforth
# 在 peforth 裡面定義的東西, 回到 python interpreter 取用:
>>> peforth.main()
OK 123 constant x
OK exit
>>> peforth.vm.forth
{'obj2dict': <function object2dict at 0x000001D136934510>, 'x': 123}
>>> peforth.vm.forth['x'] --> 123
# 用 obj2dict() 把 Word 轉成 dict, 這是 see 的準備
>>> peforth.vm.forth['obj2dict'](peforth.vm.tick('+'))
{'__class__': 'Word', '__module__': 'projectk', 'name': '+', 'xt': <function xt at 0x000001D1368F28C8>, 'immediate': False, 'help': '( a b -- a+b) Add two numbers or concatenate two strings.', 'comment': '', 'vid': 'forth', 'wid': 51, 'type': 'code'}
[x] see code words
# json 需要先給它 obj2dict() function 才能處理我們的 object
OK py> json.dumps(tick('+'),indent=4) .
Failed to run <Word '</pyV>'>: Object of type 'Word' is not JSON serializable
Continue, Debug, or Abort? [C/d/a] a ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# 從 peforth 裡面定義轉換 function
<py>
def object2dict(obj):
#convert object to a dict
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d
push(object2dict)
</py>
^D
OK .s
0: <function object2dict at 0x000001D136934510> (<class 'function'>)
OK constant obj2dict
OK exit
# 有了轉換 function 就可以讓 json 完成工作
>>> import json
>>> print(json.dumps(peforth.vm.tick('+'),default=peforth.vm.forth['obj2dict'],indent=4))
{
"__class__": "Word",
"__module__": "projectk",
"name": "+",
"xt": {
"__class__": "function",
"__module__": "projectk",
"source": "def xt(_me=None): ### + ###\n push(pop(1)+pop()) \n",
"name": "+"
},
"immediate": false,
"help": "( a b -- a+b) Add two numbers or concatenate two strings.",
"comment": "",
"vid": "forth",
"wid": 51,
"type": "code"
}
>>>
[x] code object 希望能帶 source code 以供 see
OK 45 @ dir .
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars',
'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars',
'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize',
'co_varnames'] OK
OK --> 不行, code object 裡面不能新增 attribute 也不能改裡面的
若不行, 只好模仿 Word 弄成一個 class 來裝 code object 就可以帶上 source code
或用 closure , 也就是 genxt() 的方法也是現成已經成功的辦法。也不見得比 compyle 差。
或用 dis.dis(func) 也好, 更具視覺效果
[x] 想到給 code object 加上 source code 顯示的辦法了, 引進 class Comment, 類似 class Word
但是 do nothing (由 phaseA phaseB 實現) 只帶著 comment comma(Comment('lalalal')) 進
dictionary 裡去躺著,等 see command 來利用。
OK py: comma(Comment("lalala"))
OK here
OK .
637 OK 636 @ .
lalala OK 636 @ type . --> <class 'projectk.Comment'>
OK 636 @ .
lalala
OK 636 @ execute -->
Failed to run <Word 'execute'>: must be str, not Comment
Continue, Debug, or Abort? [C/d/a] a
[x] modify phaseA phaseB to support Comment class
--> done!
[x] modify ::, :>, </py>, and </pyV> to add comment
[x] 目前 literal 仍被當一般 function 用 dis.dis() 顯示 --> 改成顯示 literal
OK 339 @ . # 已知 339 處是個 literal function
<function xt.<locals>.f.<locals>.literal at 0x000001ED9B6579D8> OK 339 @ :> __name__ .
OK 339 @ :> str . # 印出 readable 的方法
Literal: pop(). <class 'str'> OK
--> 可以修改 toString 了
==> see 終於完成了!!!
[x] 其實 __doc__ attribute 就是用來放說明文字的 . . .
--> 錯!
Failed to run <Word '</py>'>: 'code' object attribute '__doc__' is read-only
Continue, Debug, or Abort? [C/d/a]
可是我試過了呀!? 如下:
00035: RET (<class 'NoneType'>)
00036: Literal: \\n|\\r <class 'str'>
00037: RET (<class 'NoneType'>)
00038: lambda:push(eval(vm.greeting())) (<class 'projectk.Comment'>)
00039: (<class 'function'>)
7 0 LOAD_GLOBAL 0 (push)
2 LOAD_GLOBAL 1 (eval)
4 LOAD_DEREF 0 (eval_code)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 RETURN_VALUE
OK 39 @ .
<function xt.<locals>.<lambda> at 0x0000017E8D269598> OK
OK 39 @ dir .
['__annotations__', '__call__', '__class__', '__closure__',
'__code__', '__defaults__', '__delattr__', '__dict__',
'__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__',
...snip...]
OK 39 @ :> __doc__ .
None
OK 39 @ :: __doc__="abc"
OK 39 @ :> __doc__ .
abc OK
這是 : version py> vm.greeting() ; // ( -- revision ) print the greeting message and return the revision code
compile() 出來的 eval_code, exec_code 的 __doc__ 都是 read-only, 但是
包過一層 lambda 之後就可以編寫了。 <------ 真相大白!!
--> </py> 直接 comma(exec_code) 實在沒有好處, 犧牲了 __doc__ 又
迫使 phaseB 無謂地變得複雜。
--> [x] 改掉!
[x] these lines are strange,
"" value description ( private ) // ( -- "text" ) description of a selftest section
[] value expected_rstack ( private ) // ( -- [..] ) an array to compare rstack in selftest
[] value expected_stack ( private ) // ( -- [..] ) an array to compare data stack in selftest
0 value test-result ( private ) // ( -- boolean ) selftest result from [d .. d]
[] value [all-pass] ( private ) // ( -- ["words"] ) array of words for all-pass in selftest
the "( private )" become prefix of their word.help !
--> value command gets stack diagram ?
--> ( command 看到 last 沒有 help 就把後續的 (...) comment 加進去了! 應該限制
compiling state 才這麼做。
[x] *** debugging, OK now. RI: constant and value were in trouble due to that I
changed the Comment word and the way to compile code objects.
[x] python shell and eforth 互相參考手上的資料
>>> peforth.main()
OK 0 constant shell # peforth 定義的變量
OK exit
# 從外面把 globals() 給它
>>> getattr(peforth.vm,'forth')['shell']=globals()
>>> peforth.vm.forth
{'obj2dict': <function obj2dict at 0x000002C8D8F5B1E0>,
'description': '', 'expected_rstack': [], 'expected_stack': [],
'test-result': 0, '[all-pass]': [],
'shell': {'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <class '_frozen_importlib.BuiltinImporter'>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'peforth': <module 'peforth' from 'c:\\Users\\hcche\\Documents\\GitHub\\peforth\\peforth.py'>}}
>>> peforth.main()
OK shell .
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <class '_frozen_importlib.BuiltinImporter'>,
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'peforth': <module 'peforth' from 'c:\\Users\\hcche\\Documents\\GitHub\\peforth\\peforth.py'>}
OK
# 從外面 DOS copy-paste 進來,一氣呵成 (不要 indent, 用 block mode)
python
import peforth
peforth.vm.dictate('0 constant shell')
peforth.vm.dictate('// ( -- dict ) 最外層 python interpreter 的 globals()')
getattr(peforth.vm,'forth')['shell']=globals()
peforth.main() # 從 python interpreter 切換進入 peforth
\ 進入了 peforth interpret state
<accept> \ 從 terminal 收取跨行 input lines
<py>
import sys
push(sys)</py> constant sys
// ( -- sys ) The sys module. Try: sys py: help(pop())
</accept> \ ( -- string T|f ) 從 terminal copy-paste 進來的 string
[if] tib.insert help sys [then]
[x] examples tools utilities goodies 範例 栗子 例子
\ 列出所有的 code words
<py> [w.name for w in words['forth'][1:] if 'code' in w.type] </pyV>
\ 列出所有的 selftest passed words
<py> [w.name for w in words['forth'][1:] if 'pass'==getattr(w,'selftest',False)] </pyV> . cr
\ 列出所有 immediate words
<py> [w.name for w in words['forth'] if getattr(w,'immediate',False) ] </pyV> . cr
\ 把尾巴 2 個 TOS 切出來成為單獨的 list (array)
( -2 ) >r py: t,vm.stack=stack[rtos(1):],stack[:rpop(1)];push(t)
--> slice
\ Execute DOS command
OK <py> exec('import os',globals(),globals())</py> # import the os module
OK py: os.system('dir')
Volume in drive C is Windows
Volume Serial Number is 2EA4-3202
Directory of c:\Users\hcche\Documents\GitHub\peforth
2017-08-23 09:31 <DIR> .
2017-08-23 09:31 <DIR> ..
2017-07-31 20:35 65 .gitattributes
2017-06-25 13:31 18,226 voc.f
2017-08-25 13:03 <DIR> __pycache__
10 File(s) 178,951 bytes
3 Dir(s) 264,579,960,832 bytes free
OK
# But after <py> os.system(r"cd c:\Users\hcche\Documents\GitHub\ML\WH300")</py>
the peforth working directory is not changed. It changes only the temperary shell.
\ copy 以下 comment (用 np++ column mode) 從 DOS box Ctrl-V 一路跑起來
<comment>
python
import peforth
peforth.vm.dictate('0 constant shell')
peforth.vm.dictate('// ( -- dict ) 最外層 python interpreter 的 globals()')
getattr(peforth.vm,'forth')['shell']=globals()
peforth.main() # 從 python interpreter 切換進入 peforth
\ 進入了 peforth interpret state
<accept> \ 從 terminal 收取跨行 input lines
<py>
import sys
push(sys)</py> constant sys
// ( -- sys ) The sys module. Try: sys py: help(pop())
</accept> \ ( -- string T|f ) 從 terminal copy-paste 進來的 string
[if] tib.insert help sys [then]
</comment>
\ DOS command line one-liner to print the path environment variable
c:\Users\hcche\Desktop>python -m peforth s' push(os.get_exec_path())' compyle execute (see) bye
[x] <accept> <py> does not work when unless putting <py> to next line <---- problem
--> rest of the line after <accept> should be the first line of the multiple lines
[x] OK include c:\Users\hcche\Documents\GitHub\ML\WH300\wh300.f
C:\Users\hcche\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
"This module will be removed in 0.20.", DeprecationWarning)
Failed to run <Word 'sinclude'>: pop from empty list
Continue, Debug, or Abort? [C/d/a] a
OK
--> possibly because rstack are to be used to return while reset() ( stop command )
clears the rstack. --> 應該是猜對了。 stop command 只能中斷 outer loop 不能把 rstack 清掉!!
[x] let <accept> <text> auto indent. Use spaces before </accept> </text> as the common strip.
--> study <text> </text> 直接用 BL word 把 </text> 之前的 spaces 都忽略掉了, 這裡要改一下。
--> code test push(nextstring('[^ ]')) end-code test 123 得到:
0: {'str': ' ', 'flag': True} (<class 'dict'>)
1: 123 7Bh (<class 'int'>)
用來取得 </text> 之前的 spaces --> 這只是一法,也不太好。
--> 不如取所有 lines 的 leading spaces 之最大公因數,一律刪除就對了。
1. 切成 lines in an array
</text> :> splitlines() ( [lines] )
2. 算出每行的前導 spaces 個數
len - lstrip
OK s" abc" py> len(pop()) tib.
s" abc" py> len(pop()) \ ==> 7 (<class 'int'>)
OK s" abc" :> lstrip() py> len(pop()) tib.
s" abc" :> lstrip() py> len(pop()) \ ==> 3 (<class 'int'>)
OK
3. 取最小值,
OK py> min([1,2,3]) tib.
py> min([1,2,3]) \ ==> 1 (<class 'int'>)
OK
4. 每行都去除這麼多前導 spaces
[ e for e in m]
cls dropall <accept>
<text>
line1
line2
line3
line4
line5
</text> constant lines
</accept>
drop tib.insert
lines :> splitlines() constant [lines]
<py> map(lambda x:len(x)-len(x.lstrip()),vm.forth['[lines]'])</pyV>
constant leading-spaces // ( -- map ) 只能用一次!
\ 檢查 leading-spaces 有兩種方法,後者才漂亮
\ <py> [i for i in vm.forth['leading-spaces']]</pyV> tib. \ check leading-spaces
\ leading-spaces py> list(pop()) .
\ OK leading-spaces py> list(pop()) . # 如果 map 不大這個可以考慮
\ [12, 16, 16, 16, 16, 8] OK
\ OK leading-spaces py> list(pop()) . # map 之類的 iterator 都不能 rewind/reset
\ [] OK
leading-spaces py> min(pop()) constant common-indent
[lines] common-indent <py> [i[tos():] for i in pop(1)]</pyV> nip constant [result]
result py> "\n".join(pop()) constant result // ( -- string ) the cooked multi-lines string
: -indent ( multi-lines -- cooked ) // Remove common indent of the string
:> splitlines() ( [lines] )
<py> map(lambda x:len(x)-len(x.lstrip()),tos())</pyV> ( [lines] map[^spaces] )
py> min(pop()) ( [lines] indent )
<py> [i[tos():] for i in pop(1)]</pyV> nip ( [result] )
py> "\n".join(pop()) ;
code -indent
lines = pop()
array = lines.splitlines() # [lines]
spaces = map(lambda x:len(x)-len(x.lstrip()),array) # [spaces]
indent = min(spaces) # number of common indent
cut = [i[indent:] for i in array] # [cuted lines]
push("\n".join(cut)) end-code
// ( multi-lines -- cooked ) Remove common indent of the string
bingo! it works!
[x] don't need to use map in -indent, use [f(i) for i in lines.splitlines()]
should be enough --> Yes! The following two lines are equivalent:
spaces = map(lambda x:len(x)-len(x.lstrip()),array) # iterator
spaces = [len(x)-len(x.lstrip()) for x in array] # list
[x] Start to use peforth for the wh300 project . . .
用 peforth 來實現 wh300
第一個好消息就是 import module 變成 forth word 成功了!!
<py>
import numpy as np
push(np)
</py> constant np // ( -- numpy ) The numpy module
OK np .
<module 'numpy' from 'C:\\Users\\hcche\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\numpy\\__init__.py'> OK
OK
--> import to globals() is the best way. The above method is interesting but not the best.
--> Done ! wh300.f works fine now.
[x] -indent 很聰明地 " "*100 的花招把 </text> 之前的線索給毀了!!! 目前變成過度 indent.
--> 過度 indent 修好了, constant 的 runtime 又出問題。因為是 runtime, root cause 很難找。
Root cause : 下面 lambda 的 code 內縮了,應該不要。所以是 -indent 有問題。
str__', '__subclasshook__'] OK py> dictionary[456].__doc__ .
lambda:exec(
source = '\tpush(getattr(vm,"{}")["{}"])'.format(current, last().name)
last().xt = genxt('constant',source)
if not getattr(vm,current,False): setattr(vm,current,{})
exec('getattr(vm,"{}")["{}"]=pop()'.format(current, last().name))
) OK 123 constant x
Failed to run <function xt.<locals>.<lambda> at 0x000001C0C39B61E0>: unexpected indent (<string>, line 2)
Continue, Debug, or Abort? [C/d/a] a
OK
--> 對照 ok of 'see constant' 可見得上面問題版的 lambda source code 裡有多的 indent
------------ Definition in dictionary ------------
00456: lambda:exec(
source = '\tpush(getattr(vm,"{}")["{}"])'.format(current, last().name)
last().xt = genxt('constant',source)
if not getattr(vm,current,False): setattr(vm,current,{})
exec('getattr(vm,"{}")["{}"]=pop()'.format(current, last().name))
)
--> 先用醜版面過關取得完整功能, 再來對付它。
--> interpret state ok, try compile --> ok too --> so what's the problem..it's clear
當 <py> 之後跟著兩個 space 時其實這個實驗就已經複製到問題了, 厲害的是要到 test 的
runtime 才會執行 lambda 從而觸發到 unexpected indent ... 難怪這麼難抓!!
: test
<py>
a=1
b=2
c=3
</py> ;
--> breakpoint 在 -indent 當 last==constant 時
code -indent
if debug and last().name=='constant': pdb.set_trace() <--- 斷到了
...snip....
--> constant 改到有問題的 <py>..</py> 版本 --> 看看這時 -indent 收到啥
|(Pdb) p lines
|' \n source = \'\\tpush(getattr(vm,"{}")["{}"])...snip...
^---- 這個 space 就是問題所在了 !!!! 真難找。
--> Root cause: in constant source code, after the <py> an extra space was there!
--> See Ynote : "peforth -indent command indent 問題探討-- 成功了! 扫描_20170828180311 _peforth_"
[X] reset() 能不能強一點? panic() 好幾次很煩....也許有意義?
[x] compyle 裡用到 lambda 來產生 function 有問題!
# 這個可以!
>>> s = '''
... dd = {'a':123,'b':456}
... print(dd)
... v = [dd[i] for i in dd] # 取得所有的 value of a dict
... print(v)
... '''
>>> exec(s) # <----------- 直接執行 exec() 很好,沒問題
{'a': 123, 'b': 456}
[123, 456]
--
# 經過 lambda 之後 local name space 就有怪現象了
# 如下不行了, 這是經過 lambda 之後產生的結果。 compyle command 不要用 lambda . . . .
... s = '''
... dd = {'a':123,'b':456}
... print(dd)
... v = [dd[i] for i in dd] # 取得所有的 value of a dict
... print(v)
... '''
>>> f = lambda:exec(s)
>>> f()
{'a': 123, 'b': 456}
NameError: name 'dd' is not defined
>>>
--> compyle 裡改用 genfunc(source) 來產生 function
----- this snippet works fine ------------
<py>
# python does not support annoymous function. But it supports closure,
# so we can recover it. genfunc("body","args") returns a function which
# is composed by the given source code and arguments.
def genfunc(body,args):
local = {}
source = "def func({}):".format(args)
# args is something like "", or 'x, y=123,z=None'
if body.strip()=="":
source = source+"\n pass\n";
else:
source = (source+'\n{}').format(body)
try:
exec(source,globals(),local)
except Exception as err:
panic("Failed in genfunc(body,{}): {}\nBody:\n{}".format(args,err,body))
local['func'].__doc__ = source
return local['func']
push(genfunc)
</py> constant genfunc // ( -- func ) function generater genfunc(body,args)
genfunc <py> pop()(' print("hi")',"")</pyV> :: ()
\ ==> hi
( arguments ) s" x,y"
( body ) <text>
result = x**2 + y**2
print(result)
</text> -indent
genfunc :> (pop(),pop()) constant f // ( -- func ) f(3,4) prints 25 which is 3^2+4^2
f :: (3,4)
\ ==> 25
----- this snippet works fine ------------
結果:
^D
hi <--- 正確,正確
25
Multiple-line mode is on, Ctrl-D switches it off.
OK
--- genfunc() 進了 project-k kernel -----------
( name ) s" lalala"
( arguments ) s" x,y"