Forwarded from RWTG9Y4's STDOUT
好消息 好消息
现在你的 Chrome 可以直接造成系统 BSOD 啦
立刻在地址栏输入 \\.\globalroot\device\condrv\kernelconnect 领取蓝屏大礼包一份
* 就算是放在 <a href/> 里的链接也可以造成蓝屏
现在你的 Chrome 可以直接造成系统 BSOD 啦
立刻在地址栏输入 \\.\globalroot\device\condrv\kernelconnect 领取蓝屏大礼包一份
* 就算是放在 <a href/> 里的链接也可以造成蓝屏
duangsuse::Echo
https://github.com/ice1000/arend-language-server/blob/88dd2e94ea7ae564a743d349b93487dd5aa4b5f8/src/main/kotlin/server.kt 草,原来冰封那么厉害也没有写自己的 Argument Parser... 我还以为函数式爱好者都痛恨 (org.apache.commons.cli) 需要 (opt as Options).addOption(Option.builder("i").build())…
https://github.com/ice1000/jimgui/blob/master/core/test/org/ice1000/jimgui/tests/Demo.java ... 看了以后我对冰封哥的审美有点失望
虽然这只是一个直接的重写,我看出 jimgui 没有比 ImGui 本身更高的封装,它仅以 add container 的方式暴露了 tree ,这不符合之前写 TkGUI 时我的期望。
这里也有一个 initNewFrame + listen keyEvent & StringBuilder & draw text 的示例
总的来说是很重视性能的一个 JNI 封装, 利用了Critical Native ,从不在 Java/C++ 之间传输 primitive (array) 外的数据(这是十分推荐的);也会处理 String/std::string 缓存的问题(感觉管得有点宽,应该解耦了) 甚至可以自定义封送 转换函数
用了 intFlag
看了一会想点 star ,突然发现我 GitHub 好像被 @ice1000 ban 了,现在还没有解除一样
可能是以前冒犯过他吧,觉得应该解除了啊,唉🌚
找了半天没找到他之前发的 JLine ,找到这个 ,代码质量……
虽然这只是一个直接的重写,我看出 jimgui 没有比 ImGui 本身更高的封装,它仅以 add container 的方式暴露了 tree ,这不符合之前写 TkGUI 时我的期望。
这里也有一个 initNewFrame + listen keyEvent & StringBuilder & draw text 的示例
总的来说是很重视性能的一个 JNI 封装, 利用了Critical Native ,从不在 Java/C++ 之间传输 primitive (array) 外的数据(这是十分推荐的);也会处理 String/std::string 缓存的问题(感觉管得有点宽,应该解耦了) 甚至可以自定义
用了 intFlag
@MagicConstant 和 @Nullable 有好的 IDE 支持看了一会想点 star ,突然发现我 GitHub 好像被 @ice1000 ban 了,现在还没有解除一样
可能是以前冒犯过他吧,觉得应该解除了啊,唉🌚
找了半天没找到他之前发的 JLine ,找到这个 ,代码质量……
GitHub
ice1000/jimgui
:sparkling_heart: Pure Java binding for dear-imgui - ice1000/jimgui
duangsuse::Echo
https://github.com/ice1000/jimgui/blob/master/core/test/org/ice1000/jimgui/tests/Demo.java ... 看了以后我对冰封哥的审美有点失望 虽然这只是一个直接的重写,我看出 jimgui 没有比 ImGui 本身更高的封装,它仅以 add container 的方式暴露了 tree ,这不符合之前写 TkGUI 时我的期望。 这里也有一个 initNewFrame + listen keyEvent & StringBuilder…
吃饭的路上(最近有点劳累过度了,思量着 ANSI BadApple 赶紧结束休息几天吧),谈到所谓“优雅性”,想了一下 ParserKt 新 LexerFeed 的问题,感觉很 complicated ,流对象的各种属性真的不好办
首先是说这个给冰封提到底有没有意义的问题(毕竟 PM 冰封是一个比较要心理准备的事情,心理难度比与 Python 红姐、九月姐 谈笑风生不低多少),最后结论是有。
虽然 jimgui 的本意未必是做“定义式”的 GUI 框架,更像是学习 JNI 设计,而且 Kotlin wrapper 很可能会有好的接口,技术交流也是不应有太多压力的。
TkGUI 的代码生成方法利用了 Python 无编译期/运行期,虚拟机相关组件基本可用的动态性,以及动态类型;很难(或者说意义不大)移植到 Java ,但我的本意是 GUI 可以这么写, ImGui 的做法可以说是业界惯例(就我的观察, GTK, Wx 的大部分封装不需要为子控件选择 parent, 但没有一个支持树形代码定义一个视图,即便其语言有足够表现力),Java 的 Swing Frame,Panel 和 Fx Stage,Scene,Group 都必须用 mutate 对象的方法「创建」模板化的视图树(当然这是过程式的自然映照,无可厚非), Qt 和 C#, VB 有 uic 这样的 code generator ;而 TkGUI 的 way 更像是 parser combinator 那样,尽可能少用外部工具,直接在语言里组合。
这个 way 就是一句话,“优美的代码能直观地反映它所处理数据的结构”,程序结构和数据结构相互照应、谐调统一,虽然会有额外开销,但一件事情只有你重视了才能找到各方面的最优解决办法,否则就永远只是传说。
再谈 ParserKt 的问题,其实最初版本相较于一些同类已经可以算是优雅了(当然离我想的还更远)
几个月前的重计划里包含了“削除 Parser 里 Lexer 相关代码”的改动,可以说是解决了我心头一厌(很多 PEG 生成器都逃不开跳空格注释的问题,要么然写文法里,要么然走 lexer/parser 的老路,要么然可配置性不够好,这是比较草的,因为我觉得在 a b c “按顺序”模式里默认插跳空格的逻辑是接近正解的)
具体实现还算好, Lexer/Parser 的区分、 Token 而非 Char 流的存在,核心原因是空格和注释对语法结构是无效的——最好能无视,免得解析器混杂
scannerless parser 很好,但跳空格其实有更容易的解决方法——为 Input stream 添加 filter ,到底还是 java 那一套自由组合的 stream 最好,连 skipped whitespaces 以及 AST element spans 它都可以往
核心思想容易,实现上也有些问题—— Lexer 和 parser 在最近的语言里越来越模糊了,你可以看到 KotlinLexer 里会处理一些嵌套问题(就需要 push/pop state number 了),而且
这么做势必造成计算力的浪费(分词器和解析器对同一份数据做了类似的动作——检查它的嵌套结构),以及编程的冗余、重复代码,是应该努力避免的。
解析器与“分词器”之间的交流,显然是 parser combinator 的优势——它们的结构对程序员是完全透明的,可以自由定义、随意组合,让 Parser 去驱动其输入流上的 Lexer ,告诉分词器现在是什么状态,需不需要跳空格(例如 "" 里就不能跳);分词器是一个针对
有的观众就会问了:这么好的方法,比你高到不知哪里去的聪明人可多了,怎么就你想出来?
首先,不能说是没人想,要看编程实践怎么用、怎么组合这些技巧,不是说你去做了,效果就真的能像想象的那样好
其次,如果你没把代码重写 9遍,也容易被 Lexer/parser 和 scannerless 的那群既有实践误导,以为必须有 tokenizer ,或者流只能是一层,不能有“滤过”操作的
如果被动性[2](非阻塞,要不然无法共享 string 等词法的定义)以及 Parser 对其的主动性(传递在解析词条类型号)不能被保证, 许多人对输入字符序列的抽象不够灵活(万恶之源),使得他们不能够发现这一点。 (所以你在编程的时候,记得重复的少写一点、稀奇的功能特性多写一点,说不定还能帮助你对程序模型整体的理解)
(这种设计也很好的发扬了 ParserKt 的 one-pass 设计,而 C 系语言 // /* 注释与除号的区分早有给
但这个封装有很大问题—— ParserKt 最初只有
尽管这是根基(SliceFeed, Iterator/ReaderFeed 子类),它也是不切实际的,所以很快有了
而那些接收 Input 的 Input ,就只能用一个代理(delegate)类
如果说你组织流嵌套的方法是手工的,应该不需要滥用多态去做“动态类型”,又或者是自动的——真的到那种“可组合”的地步吗?
最后我觉得,还是做则不能打破 Lexer 需求 Input (SourceLocated) 的类型, 还是取消这样的限制吧…… 真不知该怎样解决这问题 #parser #parsing #learn #Kotlin #project #suggest
[^1] 现在我更倾向
isCompleteRead 是重新建模的(结果存逆波兰栈的)算符链解析器需要的,在非 complete read 时,可以像 Lua 一样直接进行简单的常量折叠,否则不仅不能折叠,还要存语法元素行号、前部空格等(重现原文所需的)信息
[^2] 其实我理解错了,这也是因为 LexerFeed 最开始是能自动识别底层输入的状态机,上级请求字符时肯定是要 blocking consume 直到非空格字符的,所谓非阻塞是因为对非空格单个字符它照样要处理状态转移;现在我倾向把它做成“能暂时屏蔽的自动 ws skip”一些,因为这才能真正统一复用文法/词法规则 ,虽然那样就没有花里胡哨的
首先是说这个给冰封提到底有没有意义的问题(毕竟 PM 冰封是一个比较要心理准备的事情,心理难度比与 Python 红姐、九月姐 谈笑风生不低多少),最后结论是有。
虽然 jimgui 的本意未必是做“定义式”的 GUI 框架,更像是学习 JNI 设计,而且 Kotlin wrapper 很可能会有好的接口,技术交流也是不应有太多压力的。
TkGUI 的代码生成方法利用了 Python 无编译期/运行期,虚拟机相关组件基本可用的动态性,以及动态类型;很难(或者说意义不大)移植到 Java ,但我的本意是 GUI 可以这么写, ImGui 的做法可以说是业界惯例(就我的观察, GTK, Wx 的大部分封装不需要为子控件选择 parent, 但没有一个支持树形代码定义一个视图,即便其语言有足够表现力),Java 的 Swing Frame,Panel 和 Fx Stage,Scene,Group 都必须用 mutate 对象的方法「创建」模板化的视图树(当然这是过程式的自然映照,无可厚非), Qt 和 C#, VB 有 uic 这样的 code generator ;而 TkGUI 的 way 更像是 parser combinator 那样,尽可能少用外部工具,直接在语言里组合。
这个 way 就是一句话,“优美的代码能直观地反映它所处理数据的结构”,程序结构和数据结构相互照应、谐调统一,虽然会有额外开销,但一件事情只有你重视了才能找到各方面的最优解决办法,否则就永远只是传说。
再谈 ParserKt 的问题,其实最初版本相较于一些同类已经可以算是优雅了(当然离我想的还更远)
几个月前的重计划里包含了“削除 Parser 里 Lexer 相关代码”的改动,可以说是解决了我心头一厌(很多 PEG 生成器都逃不开跳空格注释的问题,要么然写文法里,要么然走 lexer/parser 的老路,要么然可配置性不够好,这是比较草的,因为我觉得在 a b c “按顺序”模式里默认插跳空格的逻辑是接近正解的)
具体实现还算好, Lexer/Parser 的区分、 Token 而非 Char 流的存在,核心原因是空格和注释对语法结构是无效的——最好能无视,免得解析器混杂
scannerless parser 很好,但跳空格其实有更容易的解决方法——为 Input stream 添加 filter ,到底还是 java 那一套自由组合的 stream 最好,连 skipped whitespaces 以及 AST element spans 它都可以往
Map<K,V> 存储好了,这就同时解决了 AST data class 不好写的问题,在不必使用这些信息时,也提升了性能,就从根源上解决了许多联带(代码复用、类型冗余和构造器隐式参数、分词解析器如何相互协调的)问题。核心思想容易,实现上也有些问题—— Lexer 和 parser 在最近的语言里越来越模糊了,你可以看到 KotlinLexer 里会处理一些嵌套问题(就需要 push/pop state number 了),而且
>= 与 fun():P<T>= 的区分也使得它必须识别一些本该由文法处理的模式——在过去这是不可想象的,C 的词法规则相当简单这么做势必造成计算力的浪费(分词器和解析器对同一份数据做了类似的动作——检查它的嵌套结构),以及编程的冗余、重复代码,是应该努力避免的。
解析器与“分词器”之间的交流,显然是 parser combinator 的优势——它们的结构对程序员是完全透明的,可以自由定义、随意组合,让 Parser 去驱动其输入流上的 Lexer ,告诉分词器现在是什么状态,需不需要跳空格(例如 "" 里就不能跳);分词器是一个针对
Feed 流的状态机,本身也是一个 Feed ,而 onChar 的时候被动进行状态转移,就可以 filter 掉那些解析器不想看的字符,同时也能选择性地保留(如语法高亮) 的数据,一举多得。有的观众就会问了:这么好的方法,比你高到不知哪里去的聪明人可多了,怎么就你想出来?
首先,不能说是没人想,要看编程实践怎么用、怎么组合这些技巧,不是说你去做了,效果就真的能像想象的那样好
其次,如果你没把代码重写 9遍,也容易被 Lexer/parser 和 scannerless 的那群既有实践误导,以为必须有 tokenizer ,或者流只能是一层,不能有“滤过”操作的
如果
LexerFeed 的(这种设计也很好的发扬了 ParserKt 的 one-pass 设计,而 C 系语言 // /* 注释与除号的区分早有给
InfixPattern 扫描操作符的 TriePattern 专定子类可轻易完成,PKT 的组合性不加盖的)但这个封装有很大问题—— ParserKt 最初只有
Feed { val peek; fun consume() } ,不像一些 nextChar() 或 curChar() 数据视口不一致、命名迷惑的框架,它的流模型只允许程序员着眼一项(最本质的问题),结束时抛 Feed.End 异常尽管这是根基(SliceFeed, Iterator/ReaderFeed 子类),它也是不切实际的,所以很快有了
Input(s: Feed): Feed, SourceLocated, ErrorHandler [1],以及一大堆 Feed 上试着 (this as Input) 的扩展函数,允许解析器带行号,尽量减小开销(统计行号信息是要在 Char 输入上,而一些输入根本无需 Input 的一些成员)而那些接收 Input 的 Input ,就只能用一个代理(delegate)类
Input.By 去 proxy 这 underlying stream 实现的一些特性,这种问题严重后有点像“责任链”的字面含义——不断尝试 unwrap 一个 (可能是Input的)Feed ,寻找某个 trait 的实现者。如果说你组织流嵌套的方法是手工的,应该不需要滥用多态去做“动态类型”,又或者是自动的——真的到那种“可组合”的地步吗?
最后我觉得,还是做
LexerInput(s:Input): Input.By 比较好,这样 LexerInput(Input(s=SliceFeed(Slice("wtf") ))) 这样的二层就会成为必要的组合法,如果需要其他层,[^1] 现在我更倾向
Input: Feed, FeedControl, SourceLocated { val states:Map<String,Any>; val onError; val isCompleteRead:Boolean } isCompleteRead 是重新建模的(结果存逆波兰栈的)算符链解析器需要的,在非 complete read 时,可以像 Lua 一样直接进行简单的常量折叠,否则不仅不能折叠,还要存语法元素行号、前部空格等(重现原文所需的)信息
[^2] 其实我理解错了,这也是因为 LexerFeed 最开始是能自动识别底层输入的状态机,上级请求字符时肯定是要 blocking consume 直到非空格字符的,所谓非阻塞是因为对非空格单个字符它照样要处理状态转移;现在我倾向把它做成“能暂时屏蔽的自动 ws skip”一些,因为这才能真正统一复用文法/词法规则 ,虽然那样就没有花里胡哨的
List<Triple<Char,Int,Int>> 了(毕竟有效性在那)GitHub
ParserKt/ParserKt
Naive one-pass recursive descent, scannerless parser framework for Kotlin - ParserKt/ParserKt
duangsuse::Echo
https://github.com/ice1000/jimgui/blob/master/core/test/org/ice1000/jimgui/tests/Demo.java ... 看了以后我对冰封哥的审美有点失望 虽然这只是一个直接的重写,我看出 jimgui 没有比 ImGui 本身更高的封装,它仅以 add container 的方式暴露了 tree ,这不符合之前写 TkGUI 时我的期望。 这里也有一个 initNewFrame + listen keyEvent & StringBuilder…
被冰封有理有据地怒斥了一顿…… 下次我还得委婉点,不对,得先对相应框架、库去学习一个 ,还得仔细对下稿子,不能搞错客观事实
冰封还说我对
Optimization for strings. That jimgui by default uses an inefficient way to convert java.lang.String into byte arrays that C++ is happy with. You can customize the string-to-bytes function yourself by using org.ice1000.jimgui.util.JImGuiUtil.setStringToBytes the default caching JImGuiUtil.cacheStringToBytes(), or use the more efficient alternative to java.lang.String -- org.ice1000.jimgui.JImStr, which is supposed to be created as global constants.
的理解是错误的,在此斧正注明一下
此外冰封最后说要把我 tg 也给 ban 了,可能是真的,也可能不是认真的 😰
冰封还说我对
Optimization for strings. That jimgui by default uses an inefficient way to convert java.lang.String into byte arrays that C++ is happy with. You can customize the string-to-bytes function yourself by using org.ice1000.jimgui.util.JImGuiUtil.setStringToBytes the default caching JImGuiUtil.cacheStringToBytes(), or use the more efficient alternative to java.lang.String -- org.ice1000.jimgui.JImStr, which is supposed to be created as global constants.
的理解是错误的,在此
此外冰封最后说要把我 tg 也给 ban 了,可能是真的,也可能不是认真的 😰
GitHub
GitHub - ice1000/jimgui: :sparkling_heart: Pure Java binding for dear-imgui
:sparkling_heart: Pure Java binding for dear-imgui - ice1000/jimgui
duangsuse::Echo
被冰封有理有据地怒斥了一顿…… 下次我还得委婉点,不对,得先对相应框架、库去学习一个 ,还得仔细对下稿子,不能搞错客观事实 冰封还说我对 Optimization for strings. That jimgui by default uses an inefficient way to convert java.lang.String into byte arrays that C++ is happy with. You can customize the string-to-bytes function…
第二人格🌝:等你把新 ParserKt 搞出来,再写几个编译器、语言工具出来,对他们不就有底气了吗? 何必虚心提出交流,直接上去就是一堆 LiteratePy 降维细解博文实操代码,各种领域都加上,哪怕是不准确的,也能倒逼他们出来辟谣,有利于他人学习,岂不美哉?
#dev #plt #statement
>你不要再到处提我的名字了,并不能显得你很高大上
<“我觉得自己最大的特色就是并不想让任何人觉得自己高大上,但想让深奥的技术更亲民而已”
<如果说我能离开你们发展这么久(当然我并不会道德绑架自由人),却偏偏要靠着你们的名字骗小白的话,那才叫低劣呢 :x
但是,我会一直谨记这句话,不管现在能不能成功,但它是我的态度,就像三年前一样。我希望能一直这样。
一个人的名字多么狭隘,要做,就要做大的。
>你不要再到处提我的名字了,并不能显得你很高大上
<“我觉得自己最大的特色就是并不想让任何人觉得自己高大上,但想让深奥的技术更亲民而已”
<如果说我能离开你们发展这么久(当然我并不会道德绑架自由人),却偏偏要靠着你们的名字骗小白的话,那才叫低劣呢 :x
但是,我会一直谨记这句话,不管现在能不能成功,但它是我的态度,就像三年前一样。我希望能一直这样。
一个人的名字多么狭隘,要做,就要做大的。
#Java #code
是很好了 (我猜是不是用了代码生成呢?),如果要提一点激进的建议,我觉得 Box/Size 这种模型可以尽早使用
不过我可以搞个超前示例,如果以后绝句写出来了,会是这样封装:
感觉极其生草啊……
UI.render(Application().title("table").width(1200).height(500)) {
val colOpts = Column("Options").widgets(/*rendering widget instead of row-object property*/
Button(/*auto-id, must*/).text("OK").sameline(true).onClick { it.text((it.getData("rowData") as User).name) }
)
Window("w").fill().children(
Table("tbl").globalFilter(true).cellEditor(true).rowsPerPage(10).columns( //gfilter, cedit
*"name age country".split(' ').mapToArray { Column(it.capitalize()).field(it) }+arrayOf(colOpts)
))
}
TkGUI 目前无等价(Table 等 Model/View 建模到底如何做还存疑,已有 TreeWidget 可以做无 button cell 的),但有增添可能。是很好了 (我猜是不是用了代码生成呢?),如果要提一点激进的建议,我觉得 Box/Size 这种模型可以尽早使用
Application(title = "a", size = 1200 xHeight 5000) ,此外可以 Lombok 省去构造器 new,当然如果真加 Kotlin 的话绝不能用 infix fun 不过我可以搞个超前示例,如果以后绝句写出来了,会是这样封装:
引记法 瓷 「配」散的程度没有 ImGui 高,没有
引全 瓷.元素配置
物 示例:窗体应用("table", 宽高(1200, 500)) 为
晚成的量 主表:表单
实现的事 布局() = 表单(
提取自 ("name age country"切分以' ')映为组再末追(选项列),〖名〗表单.列(名取大写“不是全大写”、项=名)。、
全局过滤=真、单元可编辑=真、每页行数=10
) 名为(主表) 配填满格
其中,量 选项列 = 表单.列("Options"、钮(内文="OK")配同行 点击时,内文=(上级数据作用户)的名字。 )
UI.render( 和 Application,我觉得散是有好处的感觉极其生草啊……
吃饱了没事干,去研究这个像 builder 但却非常函数式的框架,因为它性能高而且定义式。
我们还是要…按照这个基本法,按照《中国民众健康暂行规定》…去规避…… 12点就睡大觉,没关系的
我们还是要…按照这个基本法,按照《中国民众健康暂行规定》…去规避…… 12点就睡大觉,没关系的
duangsuse::Echo
#Java #code UI.render(Application().title("table").width(1200).height(500)) { val colOpts = Column("Options").widgets(/*rendering widget instead of row-object property*/ Button(/*auto-id, must*/).text("OK").sameline(true).onClick { it.text((it.getData("rowData")…
我觉得我自己…… 还是要学习一个 (这个人是封装 ice1k 的 binding)
尤其是要学会写 codegen, 改天重构一下也没关系的
可是我不喜欢他的 API ,是用 codegen 去兼容还是应该改呢
尤其是要学会写 codegen, 改天重构一下也没关系的
可是我不喜欢他的 API ,是用 codegen 去兼容还是应该改呢
GitHub
newk5/flui
Library for creating lightweight declarative UI's in Java using imgui Java bindings - newk5/flui
duangsuse::Echo
LINES=68,COLUMNS=236 mvn exec:java -Dexec.mainClass=JPlayer1 -Dexec.args=a.mp4 LINES=68,COLUMNS=236 mvn exec:java -Dexec.mainClass=JPlayer -Dexec.args='a_con.mp4 a.mp4.wav' 真棒, Yuuta 的一直可以运行,我的老出问题 🌝
mvn exec:java -Dexec.mainClass=JPlayer1 -Dexec.args=BadApple.mp4 54.07s user 8.04s system 119% cpu 51.925 totalmvn exec:java -Dexec.mainClass=JPlayer 42.69s user 7.59s system 120% cpu 41.633 total Yuuta 又赢了。 好了,睡觉吧,争取下次能写出性能更好的版本来 😂
*注: Yuuta 原版是 BufferedWriter+StringBuilder 缓冲的,没有多余 flush ,但我们为了避免帧撕裂 flush 了许多次(有效果的),从某种意义讲我们还是可以更快的
新版支持 MECH(屏幕刷新方式),NCHUNK,SPEED 参数, NCHUNK=0 时禁用 queue rendering, -1 时多线程 queue, 默认环形缓冲区 queue
为测试我给原版支持了 SPEED 参数,设置得足够大使
Thread.sleep 不会运行。二倍速,第一个是 Yuuta 的,第二个是我的(bug 关系最后5s没有显示出 QAQ) ,最后一个是老大哥 C++ 的原速播放