duangsuse::Echo
722 subscribers
4.29K photos
130 videos
583 files
6.51K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
#project Lime 今天下午又有一些变更,总的来说:
1. OOP 支持, Ruby 由于足够灵活方便所以(Ruby 版本)没有内建,而是包 std/oop 使用插件(当然也有 Lime)实现的
具体工作方法可以等 wiki

例子:
(10.times (do (th)
(puts "Hello, world! #:#{th}")))

(-> File std::File)
(-> a_file (File::open 'a.txt :r))
(puts (a_file.read))

FooHash::FooKey::NestingClass::new.call_a_func

(class A
(super std::Object)
(def self.classmethod (puts 'a))
(def a_method 1))

(class B
(super A)
(include FooHash::FooMod)
(initialize)
(def a self::a)
(def a= (value)
(self::a= value)))

(r :(B::new).a) ;=> nil
(-> b_obj (B::new))
(b_obj.a= 1)
(b_obj.a) ;=> 1
(b_obj.a_method) ;=> 1
(b_obj.class) ;=> "B"
(b_obj.class.superclass) ;=> "A"

P.S: 最原始的其实是这样
(-> B (=>
name: "B"
class: "std::Class"
superclass: "A"
;......
(-> A (=>
name: "A"
class: "std::Class"
superclass: "std::Object"
#a_method: (# 1)
classmethod: (# (puts 'a))))


2. 详细了一下项目方案...
包括 CI, Spec, Wiki, 文档和主页之类

3. 内部的几个 Lime dispatch 绑定改名,详细文件和 FCL 结构,一点开发计划...

4. 语法修改支持更多 Symbol 操作, 详细化了 Lime 库\插件支持
duangsuse::Echo
#project Lime 今天下午又有一些变更,总的来说: 1. OOP 支持, Ruby 由于足够灵活方便所以(Ruby 版本)没有内建,而是包 std/oop 使用插件(当然也有 Lime)实现的 具体工作方法可以等 wiki 例子: (10.times (do (th) (puts "Hello, world! #:#{th}"))) (-> File std::File) (-> a_file (File::open 'a.txt :r)) (puts (a_file.read)) F…
展开器使用了更加灵活的方式:
现在只有 (. builtin_expanderid *args) 是亲定的了,其他前置展开器都变成普通的 Macro, 类似这样:
module Lime
module Builtins
symbol '^#', 'Create a macro object'
def macro_ctor(args_or_body, body = nil)
body.nil? ? Lime::Macro.new([], args_or_body) : Lime::Macro.new(args_or_body, body)
end
make_symtbl
end
end
考虑到 还有别的项目待做,先只做 Ruby 和 Java 解释器算了
等等我就把理论说完吧(

Lime 原生类型
Type       | (tostring T) | textual repr.
Macro | lmacro | (# arg_tbl body) (# body) ; by built-in macro ^#
Hash | lhash | (=> key1: value1 key2: value2) ; by built-in macro ^=>
List | llist | () (()) (()())
String | lstring | 'string "string"
Symbol | lsymbol | :a :"it's a symbol" :(car list) :'ssss'
Bool | lboolean | #t #f
Number| lnumeric | 0x21212i32 0b3232 43 0.4 768f32
Nil | lnull | ⚪️ () ; expanded to nil


BNF (或许是伪造的,反正也只是参考罢了
(或许应该支持注释和 debug info 和跳过空白,还有一点sugar 大概有
ending -> ' '|')'|'\t'|'\n'
number -> (0x|0b|0o) [0-9]* (u8|i8|u16|i16|u32|i32|u64|i64|u128|i128|f32|f64) ending
stringa -> '\'' string_data ending
stringb -> '"' string_data '"'
string -> stringa|stringb
nil -> ⚪️
bool -> '#' t|f
symbol -> ':' string|list ; 其实有一些特殊逻辑...
list -> '(' obj* ')'
obj -> list|number|string|nil|bool|symbol|
其实说句真心话... 这里就是 BNF 范式是 100% 正确也不能表达所需要的特殊逻辑啊...
内部定义的宏:
-> define
-? defined?
-x undef
<- read
. send
=> hash
# macro
: as_symbol
:< back_symbol
:' as_sexp
' as_array
" as_string_array
~ sequence
~~ must_sequence
` loop
`` must_loop
? cond
% typeof
:: index
::= indexeq
ext< loadext
ext> unloadext
require require
eval eval
dup dup
^ car
$ cdr
λ lambda ;就是让 macro 内联上当前(全局,Lime里没作用域的概念)环境变量而已
@ puts
@> warn
@< input
#< macro_args
#> macro_body
[] index_dynamic
[]= indexeq_dynamic
[]? haskey
[]- length
[]* allkey
"- strlen
"< gsub
"> match
"? is_include
": locate
+ add
++ inc
-- dec
- sub
* mul
/ div
** pwr
% mod
> lt
< bg
>= le
<= bg
<=> cmp
<< shl
>> shr
& and
| or
! not
^ xor
eh errorhandler
!! raise
r valueof(just_return)
p print
-># tomacro
->> tohash
->[] tolist
->" tostring
->: tosymbol
->B toboolean
->N tonumber
->() tonil


内部定义环境:
LVERSION lime version
LENGINE lime engine
LENV lime environment
LLIBPATH lime lib path
ENV os environ
ARGV cmdline argument
LFILE expanding file
$* argv
$_ file
$__ file parent dir
$: loaded files
$! exception
$@ exception postion
$~ match
$$ pid
$? child status
$. last readline number
$= ignorecase
既然转型的函数都有了我还不如内建 OOP 算了(
我想
((" foo bar 2k).join :+)
std::Symbol::#-># 🌚
duangsuse::Echo
我想 ((" foo bar 2k).join :+) std::Symbol::#-># 🌚
其实去掉 : 也行 🌚
反而更好一些,但我不确定....
duangsuse::Echo
既然转型的函数都有了我还不如内建 OOP 算了(
不如做成 OOP 算了(逃跑
本来让插件重写 reference_missing 不就可以了吗(
duangsuse::Echo
一片混乱 🙈 这时还没考虑到内建 OO 的情况
其实 Lime 内建 OO 遵循一个非常简单的原则:

Lime 解释器展开 S-表达式时会对 Symbol 原子解引用
一般情况下,直接在环境Hash中寻找那个被引用的对象,如果找不到就转给 reference_missing 让它解决(默认总是抛出 ReferenceNotFoundError 异常)
OO 却不这样,对找不到的引用执行以下操作:

unless ref.include? '.' or ref.include? '::'
call_reference_missing
else
unless ref.start_with '.' or ref.end_with '.' or ref.start_with '::' or ref.end_with '::'
call_oop_ref
else
call_reference_missing


`oop_ref`具体做的就是以 '.' 和 '::' 切分 ref, 从左到右 join 处理路径
:: 规则:
对左表达式求值,断言结果是 Hash
如果右表达式以 '=' 结尾,返回一个宏, 类似这样:
A::B::v=
(# (v) (::= (:: A B) b v))
否则,使用rhs index左表达式求值结果
. 规则:
对左表达式求值
(r lhs)
和 :: 不同,`.` 不要求 lhs 必须是 Hash, 它会按照以下映射规则为对象寻找类:
Macro -> std::Macro
List -> std::List
Hash -> std::Hash
String -> std::String
Symbol -> std::Symbol
Bool -> std::Bool
Number -> std::Number
Nil -> std::Nil

如果不能找到,它依然会抛出错误
如果 lhs 是 Hash, . 先和 :: 一样索引,但接下来分出了两种情况:
如果结果是nil(没找到), 尝试进行方法查找:
(暂时不打算缓存和内联优化什么的
查找过程中会使用到 _class “指针” 和 _superclass “指针”:
上面的映射类有用处辣! 🌝, 映射类型会作为对象的类来检查
通过 _class 字段获取到对象的类(依然是求值),使用类似 Ruby 的方法查找算法遍历超类链检查 #methodname 字段, 如果成功,大功告成!(现在还不打算支持重载,况且 OOP 本来就只是附加特性,Lime 本质上和 m4 是一样的语言)
接下来就是填充 self 的工作了,这会返回填充完成的宏,允许赛艇的写法。
不然呢? 如果找不到方法, Lime 会调用 Ruby 代码里的 lime_method_missing, 默认实现是在lhs上和寻找正常方法一样寻找 method_missing, 调用它,如果依然找不到(喷)就抛出异常
否则
如果结果是 Macro, 使用 lhs 作为 self 对这个 Macro 进行填充,返回填充后的 Macro, 否则返回结果