Package: urgent
很急语言, 一个"过渡"语言.安装pip, 命令ugt(pip install urgent,ugt --help)运行3.6, 编译3.7(3.7, 3.8上, urgent编译出的字节码可以被3.6加载, 也就是没有使用ROT4和LOAD_METHOD这些新的指令)跨版本加载用--raw_bytecodeflag.ugtcc<xxx.ugt><xxx.code>--raw_bytecode--projectbootstrap.toml后,import marshal
code_object = marshal.load(open("xxx.code", 'rb'))
exec(code_object, globals())语句(伪)let/def和rec.let x = 1
def x = 1一个意思.recrec f = x -> (f, x)是递归, 也就是自己的定义中可以出现自己.let ..., ...let x = 1, y = 2, z = ...,定义时x, y, z互不引用, 他们定义时用到的x, y, z来自外部.rec ..., ....rec x = a -> (a, y), y = a -> (a, x) , z = ...,定义时,x, y, z互相引用.If<expr> ?
    <expr>
else
    <expr>我觉得语法还行.how?fineelseemmm还阔以.Matchletx=(1,2)match(a,b,c)=>a,(1,2)=>0可以match的很多, 更多例子见后面的variants.注意, 二元运算符会被当作解构器.我们还支持view pattern.letf=x->(x,2*x)1match(f->(a,b))=>a+b# 1 + 2 * 15match(f->(a,b))=>a+b# 5 + 2 * 5Open, Import项目根目录那个hello.ugt可以拿来试, 打开ugt repl,Urgent>importHello
Urgent>print1Undefprint
Urgent>letx=Hello
Urgent>x.print11Urgent>openx
Urgent>print11import导入模块但不加载它的成员,open加载成员.
看起来似乎是python的import <mod>和from <mod> import *, 其实不是.一切都是静态的, 只有module可以被import和open.x之所以可以被open,
是因为x被分析为是模块Hello的alias.Urgent是pure的, 变量不可以多次赋值(只有绑定), 所以, 上面代码里任何使用x的地方都会索引到模块Hello.如果说python import *是有运行时开销的, 那么, 已经加载过的模块在urgent里,
无论在哪儿open都是0开销的.一种来自于ML语言的用法是, 在局部打开模块.Urgent>importHello
Urgent>letx=1Urgent>print1Undefprint

Urgent>letx=lety=2openHelloinprint11Urgent>print1Undefprint语句引导的表达式open,let,rec,def这些语句后面可以跟一个in, 表示表达式.Urgent>letx=defx=1inopenHelloinprint<|x+12连续的let,open, 这些语句, 可以不写in.Urgent>letx=letx=1lety=2letc=3openHelloinprint<|x+y+c6Urgent>print<|1+2+3Undefoperator.<|Urgent>print(1+2)Undefoperator.+中缀定义+左结合，优先级10.infixl+10<|右结合, 优先级0.infixr<|0优先级是一个整数, 可以为负.如果想要使用其他模块定义的运算符优先级和结合性, 可以open该模块.
如果不想污染作用域, 可以局部open该模块.只有and和or两个是固定的优先级, 他们的优先级都比其他二元运算符低.and和or也用在pattern matching中.and表示左右俩都要match,or表示只match一个.xmatch1or2or3=>0,xand(y,z)=>(y,x,z)VariantsdataNil,Cons(_,_)infixr::1let::=Consletl1=Cons1Nilletprint_lst=lst->lstmatch1::Consab=>...,Consab=>...,Nil=>...[]语法是Nil的简写,[a, b]这样的语法是Cons a (Cons b Nil)的简写, 所以我们可以dataNil,Cons(_,_)infixr::1let::=Consletl1=[1]letprint_lst=lst->lstmatch1::a::b=>...,a::b=>...,[]=>...局部定义的variants:letx=dataA,B,Cin(A,B,C)A# Undef: A这是用来动态create数据类型的. 注意这对于运行时来说比较缓慢. 一般来说, 还是把数据创建放到模块顶层.Variants的成员可以按名字访问:dataEither(left,right)letx=Either(1,2)x.left|>print尾递归urgent实现了尾递归, 所以, 你可以随意地写递归函数定义.我们不能说这个速度非常快, 实际上, 比起python循环, 相同情况下我们的尾递归性能只有其一半,
更别说我们还有柯里化.然而, 既然你在看了, 那我可以开心地向你保证,这是Python世界最快的, 且货真价实的尾递归实现.其基本原理相当简单, 你可以在codegen.py的preload方法里找到一个用字节码书写的,
优化到极致的尾递归scheduler.我会在非尾递归调用点应用这个scheduler,
你能同通过阅读compiler.py的v_tco以及v_call方法, 来进一步理解尾递归优化的实现.Python函数调用f.(a,b,c)像这样, 调用时加个点的函数, 就是按照Python的调用约定. 这并不和我们的尾递归优化冲突.Imperative Programming下面的代码需要加载项目目录下的base/prelude.ugt.refUrgent>letx=ref1=>()Urgent>x=>ref1Urgent>x:=2=>()Urgent>x=>ref2Urgent>!x+2=>4forUrgent>for[1,2,3](x->printx)123=>()whileUrgent>letx=ref1=>()Urgent>while{!x<10}{doprint!xinx:=!x+1}123456789=>()上面的循环暂时是尾递归写的, 之后会用Python字节码重写.for和while的实现如下:recfor=seq->f->seqmatch[]=>(),hd::tl=>dofhdinfortlf

recwhile=cond->f->cond()?dof()inwhilecondfelse()都可以良好地尾递归.项目构建urgent把所有代码编译成单个.pyc文件.# 编译sh>ugtcc<主模块.ugt><a.pyc>--project<项目文件.toml># 直接执行sh>ugtrun<主模块.ugt>--project<项目文件.toml># 启动REPLsh>ugtrepl--project<项目文件.toml>一个示例的项目文件见bootstrap.toml.packaging和project building这些方面其实还没设计好, 但先用着了. 做事第一.WIP: Traits