Giter Club home page Giter Club logo

lite's Introduction

Lite

😃 一个写了几天浪费青春浪费时光的垃圾 JVM AST 解释器脚本语言

什么情况?

某天突发奇想认为可以设计一门非常简单的 JVM 程序设计语言, 直接无需专门的分词解析过程及可以运行

2018-5-22018-5-6 在疯狂写这门语言....

而且还打算做一个 JavaScript/那门语言(那时叫 H2)/另外一门更复杂的语言(那时叫 Hydrogen)(后来又改名 H2) 一起作为很小的以「快速开发小程序」 为特性的语言

^ (我的意思是一个类似 Int 的解释器工具, 有扩展功能:快速输入 Keyword|Operator/AST 查看/Lex 结果查看/高亮/获取设置变量/脚本分享/Reflect 可视化查看(类/对象/方法/直接创建原生类型/调用方法和类型构造器)/Intent 接口 等的 Android 应用)

^ 我现在明确的告诉你们,我写这么垃圾的解释器的目标是提供 Androlua 的替代品,即使后者已经开发了两年,后者维护的用心程度是非常的 fucking, 默认打包体积已经超过了预算达到几乎 500k, 而且自带 TextWarrior 和百度 SDK, 而且虽然开源但源码没更新很久,而且 Lua 用在这上面大材小用,而且 AndroLuaJ 也不开源,而且它还加了壳,这是我忍不了的,而且他们不够优雅,因为 Lua 不够优雅,比方说

在 Lite 里你可以这么写(套用 Ruby 的例子了) (很抱歉小部分是下一个手写 parser 版本的语法, 这个版本的 parser 根本离不开 end) (如果你找到了好看的语法务必告诉我,我立刻 过来) (目前不打算支持 heredoc 和更高级的 number 表示)

import android.widget
import android.view

@botton = Button(ctx)
@text = TextView(ctx)
lay << @button
lay << @text # 这是 Lite 1.1 的语法, AST 解释器的内部隐式方法调用支持内部实现 def LinearLayout$add .....
@button.clicked do
  for i in ![华莱士 香港记者 西方记者]
    puts "你们还是 Too young! 我比 " + i + " 高到不知哪里去了"
  end
end
# next example
# 虽然这个语法已经去掉了,不过 Lite 依然可以用块和 callEasy 特性造出类似的
when input.text
  "OC<"
    puts ""
  contains "foo" exit
  nil exit if false
  length 0 puts "${input.text}"
end

(Andro)Lua 里

import 'android.widget.*'
import 'android.view.*'

local button = Button(activity)
local text = TextView
lay.addView(button)
lay.addView(text)
button.onClick=function()
  for i in ['华莱士', '香港记者', '西方记者'] do
    print("你们还是 Too young! 我比 " + i + "高到不知哪里去了")
  end
end

Lice 里

; print a string
(print "Hello " "World" "\n")
#
puts "Hello" "Word\n" # 高级的块参数填充(*varargs/name=default)这个版本就会有, 不过是出几天后的事了

; travel through a range
(for-each i (.. 1 10) (print i "\n"))
for i in 1..10
  print i "\n" # single-quote 不会转义...
end

; define a call-by-name function
(defexpr fold ls init op
 (for-each index-var ls
   (-> init (op init index-var))))
def fold(list initializer block) # paren 不是必须的
  for index-var in ls
    init = block(initializer index-var)
    # 删除, Lite 里不支持这种操作,不过你可以使用 lite[init] = .... 可以实现这种功能(Lite 的 indexLet 可以调用 Java set 方法)

; invoke the function defined above
(fold (.. 1 4) 0 +)
fold 1..4 0 { |a, b| a + b } #.... 23333 不过也是没办法, 毕竟不是 Ruby

; passing a call-by-value lambda to a call-by-value lambda
((lambda op (op 3 4)) (lambda a b (+ (* a a) (* b b))))
foo = { |op| op(3, 4) } # 不是 Lite 不支持块或者啥 lambda value(明明所有 def 函数都是 name = block 语法糖), 语法表现力不够(不支持 paren expression)... 但这是为了保证一切简单
foo do |a b|
  a * a + b * b # 你也可以用 a ** 2
end  

; to define a call-by-need lambda, use `lazy`. # call-by-need 是什么鬼,我不知道,哪个 dalao 帮我解释一下... 233333$_$

^ 即使是这样,Lite 不是一门 DSL(领域特定语言),即使它被设计为专门用来开发小型运行于 JVM 上的应用程序

当时的(H2)设计为使用虚拟机执行,虚拟机后来被命名为 AqoursVM,可是由于太麻烦的原因也没有开发,而是转而做了个 AST 解释器... (此时还有 GeekApk 等项目待完成)

最后的结果是苦战四天写了大概 6k 行代码(大多是复制粘贴,我说的是 Copy-Your-Self)后 终于还有一个解析器.... 解析器... 没写

接下来这门语言将会非常简单的使用 PEG.js 使用某些序列化操作与 Java 交互作为解析器发布,甚至不需要带当初计划的重构删除无用代码/重复代码,写测试查 coverage, 用 CI, 写详细文档和注释等

以后?

这以后肯定要重写的,钦定新版本完全独立并且 lexer(Look-Ahead stateful) 和 parser(递归下降法) 全手写, 依然将 lex 和 parse 作为两个独立进程, 并且添加 case 表达式和基于缩进的语意(现在的版本由于某些比较 fucking 的原因即使设计了依然依赖手写 end ), 为能实现 Java 接口的实现 Java 接口(如 Serializable) 名字就叫 YaLite(Yet Another Lite Interperter)(虽然不是同一门语言,或许,至少语法版本不同)

以后还有升级为 H2 的机会(就是换执行模型)...

以后 Lime(基于 Sexp 的 S 表达式解释语言) 依然会写的,放心不会很久,十年吧(皮)

关于这门语言(你也可以看代码,有一些里面的文档)

目前包括 Lexer 和写了 6% 的 Parser 在内的 AST 类 和帮助类一共 130k, 需要注意的是压缩后有 70k, 里面有不少无用的代码可以 proguard

这包括整个语言文本处理类(Lexer 和 Parser),因为是 PEG.js 解析的

需要注意的是,LuaJ 都没这么小,LuaJ 如果包含(JavaCC)解析器的话,它的解析器都比 Lite 整个要大(170k),即使 Lua 的语法并不是很复杂

BeanShell 怎么精简,它的 JavaCC 解析器类至少要占 60k.... 而 Lite 所谓 Lite 可能整个解释器都没这么大(没错,Lite 也专为体积设计)

目前计划使用 PEG.js 自动生成解释器, WIP,即使已经有一个手写 Lexer 了

语法

 true false nil
 '' "" 字符串
 1 1l 1n 1f //0x1 0b1000 number
 ^ 不打算支持进制自动换算了
 ![] [] 列表
 { a.exit } do || Proc
 { a: 1, b: 2 } Hash

import java.lang.String
import java.lang

require lib/a
require a

1 + 1 - 1 % 0x2
System.out.println 1
System::out.print @a
lite['a'] = 1
lite->a "Hello"
![a b c]->1 'a'
lite[1]
lite[@a]
{ a: 1, b: 2, c:3 }
{ a: @a, b: @b }
nil 1 23 true

trace hello world

for i in @iter
  break
  next # comment

for @i in System.collection
  puts @i

@i++ @i--

if "bad linux" in [ "foo", System.out.toString, Runtime.runtime as String ]
  puts "2333 333333 333333"

def a
  return 1

def java.lang.System.b
  return "Goodbye, cruel world"

def $java.lang.Integer.fmt a b c
  puts 'oh no'
  return String.format a b c

def neg i
  return -i

def not_ i
  return !i

@a = System.in
b = '2'

import java.lang.String
str = String("Be a good guy") # Construct a java object
str = java_lang_String("yes") # alternative java Class identifier
str = java.lang.Integer(1) # Bad but acceptable
str = neg(233f)
@notnot = not true # must not be true....
Hashtable()[Integer(1)] = "kotlin f**king comming"
Hashtable()::1
def tbl
  {a:"Hello"}

puts tbl()::a
scope
  @b = tbl()
  @b->a "Goodbye"
  @b->c { puts @self::a }
  @b.c # LiteBlock
  @b.c()

java_lang_System # identifier

while true
  break

while System.out == "a"
  if System.in == "b"
    elif a === null
      next
    else
      break

以上直接使用了 Ruby 高亮,实际上 Lite 的 Lexer 自带高亮, 使用 -lexP 就可以在 ANSI escaped terminal 上看到高亮字体

shot

duangsuse 设计了一种类似 BNF 的语言来描述 Lite 的语法

 * Complete Lite Syntax (DNF 范式, 是 duangsuse 设计的一种即使没有规则你们也能看懂的无上下文词条流模式文法描述)
 * (看起来很高大上的东西, 其实没啥用.....)
 * Lite 的一个比较特殊的地方在于使用缩进语义, 我也是为了好看... 不过如果使用递归下降法, 解析不是问题耶
 * 强制你使用 duangsuse 喜欢的 2 空格缩进代码风格, 语言本身类似 Ruby (Ruby 岛国语言好耶)
 * 有趣的语法: ![str1 str2 str3] . each { |e| puts e } if a == 1 & b === :c
 *
 * #### TABLED symbol ####
 * newline  : '\n'
 * ident    : '  '
 * l_square : '['
 * r_square : ']'
 * let      : '='
 * at       : '@'
 * call     : '()'
 * bang     : '!'
 * sub      : '-'
 * inc      : '++'
 * dec      : '--'
 * #### FINISH symbol ####
 *
 * math -> expr Maybe( '+' OR '-' OR '*' OR '/' OR '**' OR '%' OR '<' OR '<=' OR '>' OR '>=' OR '&' OR '|' OR '==' OR '===' OR '!=' OR '<<' ) expr
 * binary -> math | cast | dot | in | square | stabby
 * expression -> binary | list | table | value | incDec | not | negative | call | identifier | index | blockProcedure | doBlock
 * statement -> def | for | scope | while | if | excited_statement
 * excited_statement -> break | next | import | require | return | trace | assignment | indexLet | square | stabby | dot | incDec | call Maybe( IF expression )
 * block -> Ary( IDENT statement NEWLINE )
 * for -> FOR identifier IN expression NEWLINE block
 * while -> WHILE expression NEWLINE block
 * scope -> SCOPE NEWLINE block
 * indexLet -> expression L_SQUARE expression R_SQUARE LET expression
 * index -> expression L_SQUARE expression R_SQUARE
 * if -> IF expression NEWLINE block Maybe( Ary( IDENT ELIF expression NEWLINE block ) ) Maybe( IDENT ELSE NEWLINE block )
 * identifier -> Maybe( AT ) label
 * def -> DEF identifier Maybe( nameList ) NEWLINE block
 * call -> identifier Maybe( CALL OR exprList )
 * assignment -> identifier LET expression
 * not -> BANG expression
 * negative -> SUB expression
 * incDec -> identifier Maybe( INC OR DEC )
 * trace -> TRACE Maybe( Ary( Any() ) )
 * return -> RETURN expression
 * require -> REQUIRE Any()
 * next -> NEXT
 * break -> BREAK
 * import -> IMPORT Maybe( Ary( Any() ) )
 * value -> TRUE | FALSE | NIL | Number() | string
 * string -> '"' Maybe( Ary( Any() ) ) '"' | stringB | stringC
 * stringB -> "'" Maybe( Ary( Any() ) ) "'"
 * stringC -> ':' label
 * list -> Maybe( BANG ) L_SQUARE exprList R_SQUARE
 * table -> '{' kvList '}'
 * kvList -> Ary( label ':' expression Maybe( ',' OR NEWLINE ) )
 * stabby -> expression '->' label expression
 * square -> expression '::' label
 * in -> expression IN expression
 * dot -> expression '.' label Maybe( CALL OR exprList )
 * cast -> expression AS label
 * exprList -> Ary( expr Maybe( ' ' OR ',' ) )
 * nameList -> Maybe( '(' ) Ary( name Maybe( ',' OR ' ' ) ) Maybe( ')' )
 * nameListB -> '|' Ary( name Maybe( ',' OR ' ' ) ) '|'
 * blockProcedure -> '{' Maybe( nameListB ) Ary( excited_statement ':' ) '}'
 * doBlock -> DO Maybe ( nameListB ) block

赛艇链接

  • GitLab 上有一个叫 h2 的公开项目, 我这里不提供链接(网速...)垃圾 GFW 是不是 QOS 我
  • BitBucket 上也有个,要不然就叫 Hydrogen 的 Mercurial Repo
  • Coding 上或许也有,不过大概是空的

lite's People

Contributors

dependabot[bot] avatar duangsuse avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

lite's Issues

Java 方法对象缓存优化

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Change to the lite syntax/semantic
没有,只是大家都做这优化,我感觉这优化应该 JVM 做

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

最新动态

最终还是决定暂时重写了(简单重写)
去除重复无用代码和支持更多语法以及小特性
不去除 end

决定是使用 JFlex + PEG.js 解决解析问题, Java 能复用的代码依然复用
为了体积(和我对其它 JVM 语言不熟悉,而且大都比较复杂)依然使用 Java 编写

解析器

https://github.com/harc/ohm

https://www.lua.org/manual/5.3/manual.html#3.4.8

和作为临时草稿的 DNF

// Complete Lite Desugared Syntax(DNF 范式, 是 duangsuse 设计的一种即使没有规则你们也能看懂的无上下文词条流模式文法描述)

// Lite 的一个比较特殊的地方在于使用缩进语义, 我也是为了好看... 不过如果使用递归下降法, 解析不是问题耶
// Lite Desugared 不包含特殊的字符串语法糖,也不包含缩进语义,标准 Lite 语法经过 Lite Lexer 和 Flatter 处理后可以交由此 JavaScript Parser 解析序列化 AST
// 强制你使用 duangsuse 喜欢的 2 空格缩进代码风格, 语言本身类似 Ruby(Ruby 岛国语言好耶)
// 有趣的语法: ![str1 str2 str3].each { |e| puts e } if a == 1 & b === :c

// math -> expr Maybe( '+' OR '-' OR '*' OR '/' OR '**' OR '%' OR '<' OR '<=' OR '>' OR '>=' OR '&' OR '|' OR '==' OR '===' OR '!=' OR '<<' OR 'and' OR 'or' ) expr
// binary -> math | cast | dot | in | square | arrow | range
// range -> expr '..' expr
// paren_expression -> '(' expression ')'
// expression -> binary | list | table | value | incDec | not | negative | call | identifier | index | bracket_block | do_block | paren_expression
// statement -> def | for | scope | while | when | if | simple_statement
// simple_statement -> break | next | import | require | return | assignment | indexLet | square | arrow | dot | incDec | call Maybe( IF expression )
// block -> Ary( statement NEWLINE ) END
// for -> FOR identifier IN expression NEWLINE block
// while -> WHILE expression NEWLINE block
// scope -> SCOPE Maybe( label ) NEWLINE block
// when -> WHEN expression NEWLINE Ary( expression Maybe( expression ) NEWLINE block ) END | when_is
// when_is -> WHEN expression NEWLINE Ary( IS Ary( expression OR ) NEWLINE block ) END
// indexLet -> expression '[' expression ']' '=' expression
// index -> expression '[' expression ']'
// if -> IF expression NEWLINE block Maybe( Ary( ELIF expression NEWLINE block ) ) Maybe( ELSE NEWLINE block )
// identifier -> Maybe( AT ) label
// def -> DEF identifier Maybe( nameList ) NEWLINE block
// call -> identifier Maybe( CALL OR exprList )
// assignment -> identifier '=' expression
// not -> '!' expression
// negative -> '-' expression
// incDec -> identifier Maybe( '++' OR '--' )
// return -> RETURN expression
// require -> REQUIRE tokensAsString()
// next -> NEXT
// break -> BREAK
// import -> IMPORT tokensAsString()
// value -> TRUE | FALSE | NIL | Number | string
// string -> '"' data '"' | stringB | stringC
// stringB -> "'" data "'"
// stringC -> ':' data
// list -> Maybe( '!' ) '[' exprList ']'
// table -> '{' kvList '}'
// kvList -> Ary( label ':' expression Maybe( ',' OR NEWLINE ) )
// arrow -> expression '->' label expression
// square -> expression '::' label
// in -> expression IN expression
// dot -> expression '.' label Maybe( '()' OR exprList )
// cast -> expression AS label
// exprList -> Ary( expr Maybe( ' ' OR ',' ) )
// nameList -> Maybe( '(' ) Ary( name Maybe( ',' OR ' ' ) ) Maybe( ')' ) | nameListB
// nameListB -> '|' Ary( name Maybe( ',' OR ' ' ) ) '|'
// bracket_block -> '{' Maybe( nameListB ) Ary( ':' simple_statement ) '}'
// do_block -> DO Maybe ( nameListB ) block

Fucking deep().foo() syntax rule

puts funcking_deep () . call ()
puts funcking_deep()()

被认为是
fucking_deep() . call()
第一个 fucking_deep() 被认为是标识符

考虑要不要作用域优化

rt. 龙书撞枪系列 1 : Lice 的动态作用域实现

看了十分钟左右发现我居然已经可以理解写的内容了
我的意见是不加,因为 Lite 除非是非常严重的性能问题(而且因为 Lite 很小基本不存在性能问题)
我的看法是 良好的行为和简单的实现 > 良好的性能
(之前几个优化方案就不用说了,值得一提的是 Lite 之前我还真的特别菜的时候就在 MinVM 上设计了标识符 -> id 的优化.... 虽然 Lite 如果以后要做基于虚拟机的实现我肯定不会做那个)
首先我不可能支持 set 这种约束,然后是 Vector 的问题,Lite 实际上可以采用这种优化(本来我在 Lite 上不打算纠结性能问题的)

不过问题是 Lite 的自省能力特别强(而且我专门这么设计的...)Lite 被设计为可以访问大多数 Java API,而 Lite 本身就是纯 Java 编写的,这意味着 Lite 程序可以轻松访问解释器的 API

这样 Lite 的作用域 stack 可能就不直接了,Lite 在作用域上面我觉得还没什么优化的必要,这上面我目前保持中立看法不改变原设计

某个比较智障的可能性

其实 Lite 现在这个 样和 Lua 也差不多了,Lua 都是 industry 级别的语言了,既然我们只是想有个 Androlua+ 的替代品,为何不直接修改 Lua 和 LuaJava 呢?或许我们因为是在已有的工作量上修改还能有更好的细节处理,也能简化 Lua 的语法,顺便熟悉下纯 C 项目。

而且创建了一些东西以后,其实 duangsuse 也的确学习到了,其实这个项目可以以后再做的(据说)
((((((((((虽然体积上还是我们小一点,性能上不如(逃跑(连虚拟机都没

InScript 升级

首先说 InScript(duangsuse 有习惯把本应该记录在笔记上的文字记录在这里

InScript 名来自与 Inspect 和 Script 两词,我想让 Lite 成为一个专门扩展其他语言的 AST 解释器,所以我觉得这个名字比较可以突出它的性质

InScript 开始计划开的坑有

  • Highlights 高亮配置们
  • Ideains IDEA 插件
  • Inside InScript 打算做一个 Android IDE 的
  • instd 因为解释器本身不携带类库... 准确的说是「扩展」类库,因为 InScript 虽然是 OO 的,但是不能创建类,一切依赖「方法覆盖」
  • inspec 类似 RSpec,必须的测试框架
  • ink 包管理器
  • instruct 类 Rake 构建系统,因为 InScript 非常依赖平台原生的类库,而脚本不能而且不需要编译(最多到 AST 格式而已)
  • indoc 一个内联文档的构建工具是必须的

解释器方面打算有 Kotlin 的、ES6 的、C# 的

如果有时间还打算出 Ruby 和 C 的版本,虽然更加没有意义(

另外 Lite 变成 InScript 自然是不会没有任何改变的,实际上改动很大很大

  • 允许为块指定「全局」环境

Lite 比较蹩脚,因为不像 Ruby,有些东西不是方法(全局 LiteBlock 对象)
所以拿这个弥补一下

  • 当前 self

整个解释器(一个线程一个解释器)应该有一个全局的 self,显然 self 应该是一个函数调用的本地参数...
Lite 目前是使用填充 self 符号再调用方法的,考虑将 self 作为真正的参数

  • 无括号调用

学习 Ruby,因为有时候没有参数还要括号很蠢

以前必须这样写

System.gc()

现在不需要括号

  • InterpreterOptions

解释器允许不同的解释模式,如使用 self 填充或本地变量,不支持 @ 处理器等等

  • forIndex

for i = 0 to i >= 100 do i++
puts(i)

  • TLS errno

线程安全的 Errno,但是我觉得没有必要,现在已经安全了(一个线程一个解释器上下文)

所以确认增加了更好的 StackTrace(增加脚本行号)和 saved exception,因为 InScript 不支持异常

  • Option & Result 值

类似与 Rust,因为我们没有异常系统,必须要有办法处理异常

Rust 拥有 Option 是为了不让所有引用类型都可能为空,Rust 为安全设计,而 Java 和 Kotlin 中引用完全可能是 null,InScript 支持没有意义

Result 方便处理错误,Lite 应该要有类似的东西,不过我觉得实现 Promise 即可替换掉 Result,所以解决方案变了。

using std.Promise

Promise.try(|>
a = File.read('a.txt'))
.catch(Exception, |>

.....

)

Promise 会在 errno 被设置时「捕捉」异常,因为 InScript 是完全的 AST 解释器,Promise.try 对于每一个可能设置 errno 的语句都能进行异常处理(修改块对象)

  • statement processor

就像 ES6 的 decorator 特性一样

using std.Httpd

def Processor_get(path)
Httpd.add_route(Httpd::Methods::GET, path, self)

@get('/')
def hello_world = "你好,世界!"

Httpd.run host: '127.0.0.1', port: 8080

  • String templating / interpolating

foo = gets
foo_bar = $foo ${Bar::FOO}

  • 箭头函数

fn = (a) => puts a

hello = |> puts 'Hello'

  • Hash 支持 [] 语法

a = 1
puts {
[a]: '2333333'
WWWwwwwW: a
}.to_s

  • InScript 的新模块化模式:scope、using、inscript.unload

require 'load_scope'

using LoadedScope # 导入作用域环境

using load_scope.LoadedScope

using load_scope/LoadedScope # 先 require 再载入

scope main # 默认作用域

puts foooo # 在本地作用域和作用域链上查找

inscript.unload :LoadedScope

  • Tail Call Optimization

InScript 支持尾调用优化,所以可以节省尾递归操作的时间

但是,这不是解释器自动实现的,我懒得做 CFA(控制流分析)

scope Algorithm

fibonacci = inscript.tco do |n, ac?, ac1?|
ac |= 1
ac1 |= 1
return ac2 if n <= 1
return fibonacci(n - 1, ac1, ac + ac1)

scope main
using Algorithm

fibonacci 2333

  • case 表达式,其实我提过不过没写

Lite AST JSON Serialization

Lite JSON Ast

node

type, file, line, column

nodes

compstmt

statements : node[]

block

block_type: : string (program, brace, do, def, flow, loop, scope)
arguments : string[]
body : compstmt

identifier

is_local : boolean
label : string

def

name : identifier
def_type : string (def, noargs, expr)
body : node

for_loop

variable : identifier
expression : node
body : node

while_loop

expression : node
body : node

scope

name : string
body : node

if

elif_block expression : node body : node

if_type : string (if, if_else, if_elif)
expression : node
body : node
elif_blocks : elif_block[]
else_block : node

nop
break
next

import

package : string

require

path : string

return

expression : node

assign

name : identifier
value : node

index_assign

target : node
index : node
value : node

arrow

target : node
index : string
value : node

binary

lhs : node
operator : string (or in and lt gt le ge ne e nee ee shift to add sub mul div mod pwr sqr as)
rhs : node

unary

target : node
operator : string (neg not inc dec)

value

value : object

call

call_type : string (call, dot, index, implicit, identifier)
target : node
arguments : node[]

table

kv_pair: key: string, value: node

initializer : kv_pair[]

list

initializer : node[]

最新的 Lite AST/语法语义设计

由于某些原因还有已经连续写了快一周这个垃圾解释器而没有成果

干脆决定彻底重写

这次我用 Gradle + Kotlin + Beaver + JFlex

这个 issue 会收集之前的 AST,语义 作为新解释器的文档
新解释器先写 AST 解释器再写 parser,并且使用 AstJson 约定,可以解析使用 Lite Json AST
而 Lite 解析器和 AST 解释器完全分开设计,解析器负责解析代码并序列化为 JSON 对象,解释器负责解析 JSON 文本和解释生成的 AST

下面会详细描述 Lite 的设计

块,打包创建时的本地变量引用

rt, Lite 不支持这种代码:

def a
  @fucking_text = 'deep'
  return ->() { "It's fucking #{@fucking_text} " }
end

puts a().call

可是,其实 Ruby 里的块是在创建时打包当前本地变量的,所以你可以让块携带着本地变量的引用跨越词法作用域的大门, Lite 里这不可能。

def fucking_deep
  @fucking_text = 'deep'
  return { "It's fucking $@fucking_text" }
end

puts funcking_deep().call()

in 应该有最低优先级

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS, ArchLinux, Debian]
  • Runtime Version [e.g. Graalvm, Oracle JRE, Android]
  • Version [e.g. 1.0]

Smartphone (please complete the following information):

  • Device: [e.g. Nexus6]
  • OS: [e.g. AndroidO, MIUI]
  • Browser/Dalvik Version [e.g. SystemWebView, Legacy]
  • Version [e.g. 1.0]

Additional context
Add any other context about the problem here.

异步调用 LiteBlock race condition (Lite stack)

Describe the bug
Lite 的本地作用域 stack 会因为异步块操作导致块所访问到的作用域错位

To Reproduce
Steps to reproduce the behavior:

race = lite.proxy Runnable, {
  run: { @a = 1; Thread.sleep(Math.random() * 10); return }
}

for _ in 0..15
  Thread(race).start()
end

while true
  if @a; break # @a should always be nil
end

Expected behavior
@A should always be nil
while should run forever

Additional context
F**king bugs

语法规则错误:在一个标识符出现后所有跟随表达式成为 CallEasy 参数

#2 (comment)

目前发现了规则有一个问题:

CallEasy 会把之后所有的 expression 都当成参数:

System.out.println getb() a b c
#                                      ^ 会被当成 getb 的参数 
System.b 1 2 3 a(1) 2
#                              ^ 应该是 System.b ... 的参数,却变成了 a 的参数,而 a (1) 2 被解析为 CallEasy

a() 1 2 3

目前认为原来正确的设计是 getb() 使用了 () 来限制参数的范围,所以不会有问题
但是实际上 a() 被当成了 Call,不过这个没什么的

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.