profile
viewpoint
WuZhanBang zuluoaaa XiaMen Do what you want to do : D

zuluoaaa/makeJs 268

A sub Javascript interpreter for interpreting itself

zuluoaaa/blog 4

blog

zuluoaaa/works 2

javascript,zuiluo

zuluoaaa/acwj 0

A Compiler Writing Journey

zuluoaaa/jsjs 0

简易的 JavaScript 元循环解释器

zuluoaaa/myCanvas 0

js,canvas

zuluoaaa/opencv_extra 0

OpenCV extra data

zuluoaaa/svg-text-animate 0

A Javascript library for convert text to SVG stroke animations in the browser.

startedgoldbergyoni/nodebestpractices

started time in 5 hours

issue closedzuluoaaa/makeJs

能否给一篇文章讲解下呢?

最起码讲解下每个模块的作用,以及重要的类,方法,数据的含义吧。

看起来比较吃力,尤其是代码比较分散的情况下。

closed time in a day

azl397985856

issue commentzuluoaaa/makeJs

能否给一篇文章讲解下呢?

可以看看这个 https://github.com/zuluoaaa/blog/issues/6

azl397985856

comment created time in a day

push eventzuluoaaa/blog

WuZhanBang

commit sha ad7907b6f32ff5b04e153a29f1f499d5455bd979

Update README.md

view details

push time in 4 days

issue openedzuluoaaa/blog

开发遇到棘手的难题该怎么办?

概述

本文主要讲的是笔者近期遇到一个难题,从遇上,到尝试各种方案,踩各种坑,最后解决的心路旅程,供作参考借鉴。

前文

我们的产品是一个工具类软件(使用nwjs的桌面应用),用户可以提交自己感兴趣的链接,我们去帮忙采集里面的视频。

最近一个用户常使用的一个网站上的视频加了非常严格的水印(动态位置,从左到右移动的水印,而且还是很多个水印)

类似这样: demo.jpg

在检查了视频链接无法逆向到无水印视频的链接之后(视频链接是一个UUID),就有了本文。

笔者技能介绍

一个前端,自认为编程基础还行,写过JAVA(crud boy)。

第一步

一开始,毫无疑问,我当然是跟产品说,不行,这个做不了,去水印不现实。不过,链接里面不是有图片么,我们自己把图片合成视频,你觉得这样的降级方案怎么样? 经过一番激烈讨(si)论(bi),产品勉强同意了。但是,需要我在图片上做一些动画效果,例如图片之间的动画图片什么的,不能单纯一张图片静止不动播放几秒。

为了省钱且开发时间赶(线上急着用),我首先尝试了有没有方案能在前端直接生成视频,结果还真的有~

Whammy 这个库能将你的canvas动画转成webp(视频格式的一种)

他的原理其实就是将canvas逐帧保存到webp,最后将一组webp转成webm格式的视频)

我很快就把canvas动画写好了,然后逐帧保存,嗯,就这样搞定了~写的时候还是很easy的

但是嘛~~~缺点就出来了,速度实在是太特么慢了,视频体积也太特么大了。

在当时至少也勉强解决了一点问题,给部署上去了(又不是不能用.jpg)

第二步

前面的方案部署上线之后,我便立刻开始了优化之路,经过一下午的摸索,我发现………………这玩意没的优化空间,撑死就是把canvas动画改成webgl渲染,渲染速度快一点。

但是上面说到的两个缺点跟动画渲染速度没啥关系,把一帧动画转成webp的速度实在是慢到令人发指,最后的webp转成webm的速度也是无法忍受,最最无法忍受的是还极度吃CPU和内存。

所以,我很快就放弃了优化方案,准备重构!既然你JS速度这么慢,C++速度快啊,我用C++写不就行了嘛~自己写一个c++扩展,再打包成nodejs原生模块。

emmm,听起来似乎可行,但是,我没写过C++啊!(只在菜鸟教程上看过C++入门)

自己从0开始写是不太现实的,所以借助了搜索引擎,

先看了看C++通过图片转成视频的方案(从stackoverflow上扒了不少代码),又看了一些nodejs原生模块的教程,又看了FFMPEG,嗯,这个好强大!

一番血和泪,最后把拷贝出来的代码修修改改,使用了freeImg 打开图片,进行图片操作,逐帧编辑操作,最后调用FFMPEG合成MP4导出,

当然了,把这个C++最终编译到nwjs客户端上去执行,也是踩了不少坑。

到这里,还是存在一个致命问题,懂图像处理的同学到这里是不是发现一个问题了,没错,由于我的弱鸡,我没有用到GPU!!!这样重构出来的性能并没有比原来的方案提升太多,还是没有解决问题。

到这里,我已经快熬不住了,功能性能好歹是优化了一些,先上线吧。

第三步

后面其实一直想的是把C++改成调用GPU去实现,但是一直没时间,而且中途有统计过我们用户电脑的配置,大部分用户的电脑都没什么独立显卡……

而且不少用户都不满意这种降级方案的实现……

早在第一步的时候我就跟产品说过视频去水印的可能解决方案,深度学习标记出视频水印位置,然后使用水印原图的差值叠加的方式去水印,嗯,理论上是可行的。但是,我们团队只有一个前端和后端啊, 上哪去给你生出一个会深度学习的!

迫于产品天天给我压力,我开始去了解一些深度学习的方案了,不看不知道一看吓一跳。

似乎好像没有想象中那么难,深度学习框架都已经封装的那么完全了,似乎不懂深度学习的人也可以调用框架来训练自己的模型?

到这里的时候,其实我已经跟产品夸下海口了233333

根据网上的一大堆教程和介绍,最后决定选用tensorflow object detect api,使用官方提供的预训练模型,花了两三天终于把tensorflow-gpu版本下载了下来, 又花了几天跑了官方demo和别人开源训练好的模型,嗯,可行!

期间最痛苦的事情是自己标了几十张图片,太折磨人了。。

公司电脑显卡不太行,我拿了自己的战神笔记本1060跑了好几天,终于!!!!

用opencv调用训练出来的数据模型,识别水印位置,进行修复,保存到一个新视频里,再使用FFMPEG将音频合过来。

圆满解决了问题了。

后续

由于涉及到产品隐私问题,就不提供代码和示例了~

整个过程中,给我帮助最大的是谷歌,github,阅读英文技术文章的能力。遇到问题就谷歌一下(强烈推荐英文搜索!!!),查找解决方案,

想了解/使用一个技术框架/第三方库的最好的方法是上官网看教程,到github看issue,都找不到就看看下源码吧,说不定就有思路了。

不要把自己局限在某个技术范围上,敢想敢做233333

created time in 4 days

push eventzuluoaaa/blog

WuZhanBang

commit sha f6ce0f8353fe15f4b82873daa73fbbce4012ca41

Add files via upload

view details

push time in 4 days

starteddatitran/raccoon_dataset

started time in 11 days

startedtensorflow/tensorflow

started time in 13 days

fork zuluoaaa/opencv_extra

OpenCV extra data

fork in 14 days

startedtensorflow/tfjs-examples

started time in 14 days

startedjustadudewhohacks/opencv4nodejs

started time in 18 days

starteddenoland/deno

started time in 18 days

issue closedruanyf/weekly

[第 106 期][自荐]一个用js写的js解释器

https://github.com/zuluoaaa/makeJs

用来学习编译原理,支持大部分 JS 的核心功能了,除了对象。

closed time in 18 days

zuluoaaa

startedzeit/next.js

started time in 19 days

push eventzuluoaaa/makeJs

wzb

commit sha c9999f66560bf2637db9b743eeb3f0ca5a3081ff

Add line code comment and fix some bugs

view details

push time in 20 days

startedqazbnm456/awesome-web-security

started time in 22 days

startedbenhowdle89/grade

started time in 22 days

startedzuluoaaa/blog

started time in 23 days

started1009466147/code-generate

started time in 24 days

issue openedruanyf/weekly

[自荐]一个用js写的js解释器

https://github.com/zuluoaaa/makeJs

用来学习编译原理,支持大部分 JS 的核心功能了,除了对象。

created time in a month

push eventzuluoaaa/blog

WuZhanBang

commit sha 3d03459cb9a9b949440c05238d0c3e8ba915799d

Update README.md

view details

push time in a month

issue openedzuluoaaa/blog

编译原理:如何从0写一个js解释器

前段时间写了一个js解释器,到目前已经已经把除了对象以外的JS大部分基础功能写出来了,在此分享和回顾一下重点技术细节和实现。 https://github.com/zuluoaaa/makeJs

0 初始化

我们输入一串有意义的js字符串

1 词法分析

遍历循环输入,将字符串逐个解释成有意义的数据结构(这里用token代表这个数据结构

var a = 1

上面这行代码,会被解析成以下4个token

[{token:"var"},{token:"indent",val:"a"},{token:"assign"},{token:"number",val:1}]

对于上述的输入,将字符串转换成token数组很简单,我们只要去逐个读取输入串的值并跳过其中的空格就可以导出这个值。

但是,这只是一个开始,你可能还需要处理一些不一样的输入,必须要求你读完某个部分的值之后才能判断这个值是什么token

例如:区分== 和 = , > 和 >= ……

解决办法也很简单,直接贴实现代码

            case "<":
             next = nextChar();
            if(next === "="){
                token.type = tokenTypes.T_LE;//判断为 <=
            }else {
                token.type = tokenTypes.T_LT;//判断为 <
                putBack(next);
            }

PS:在这一步中,我们不关心语法和语义是否正确,我们只负责解析成token,是关键字就解析成对应的关键字token;如果是数字就解析成数字token,是字母我们就解析成变量token。 然后由后续的程序来处理这些问题。

2 语法分析

将token转换成AST (语法树),也就是将拿到的一组token转换成整体连接的语法结构

这一步就是整个解释器的重点了。

先举个例子

var a = 1 + 3 * 2;

所对应的语法树

       =
      /  \
     +    a
    / \
    *  1
  /  \
 3    2

之所以要把变量A放在右侧,而不是左侧,是因为我们后续会通过前序遍历来解析执行AST,这样便于求值。

上面只是一个简单的例子,这一步骤最复杂的部分就是处理各种关键字 if,else ,function,while……

处理复杂的表达式也是令人头大,各种运算符、例如 &&,>,<=,+,-,*,/,?:……

举个例子

let a = 8+6*3-2*5 > 12*3+(1+5) ? 1 : 2;

将以上的表达式解析到对应的AST,不熟悉解释器和编译器的同学(比如之前的我),往往是卡在这一步,不知所措,陷入自我怀疑...

由于这里面处理的细节处理太多了,这里只将核心架构来告诉大家,具体实现的话,大家有兴趣可以到我项目代码里面进行翻看

负责解析的主方法的核心实现

function statement(){
    let tree = null,left = null;
    while (true){
        let {token}  = gData;
        //不同关键字,跳转到对应的解析函数
        switch (token.type) {
            case tokenTypes.T_VAR:
                left = varDeclaration();
                break;
            case tokenTypes.T_IF:
                left = ifStatement();
                break;
            case tokenTypes.T_WHILE:
                left = whileStatement();
                break;
            case tokenTypes.T_FUN:
                left = funStatement();
                break;
            case tokenTypes.T_RETURN:
                left = returnStatement();
                break;
            case tokenTypes.T_EOF://EOF是整个输入串已经执行完毕了,退出解析
                return tree;
            default:
                 left = normalStatement();
        }
        //基本上每次循环只解析一行语句,这里是将多行语句组合起来,最后将整个输入串组装成一棵语法树
        if(left !== null){
            if(tree === null){
                tree = left;
            }else{
                tree = new ASTNode().initTwoNode(ASTNodeTypes.T_GLUE,tree,left,null);
            }
        }
    }
}

function normalStatement() {
    let tree =  parseExpression(0);//执行表达式解析,得到语法树
    semicolon();//检查逗号
    return tree;
}

...

上述是语法解析,下面是最最核心的表达式解析(例如解析算术表达式 1+3*(6+1)

首先定义一组前缀解析和一组中缀解析的map,根据类型自动到对应的解析方法,这样的话,我们有任何新增要解析的符号,直接往里面新增就可以了,而不需要改动函数内部的实现


const prefixParserMap = {
    [tokenTypes.T_IDENT]:identifier,//变量
    [tokenTypes.T_INT]:int,
    [tokenTypes.T_STRING]:str,
    [tokenTypes.T_LPT]:group,//括号
    [tokenTypes.T_LMBR]:array,//中括号
    [tokenTypes.T_ADD]:prefix.bind(null,tokenTypes.T_ADD),
    [tokenTypes.T_SUB]:prefix.bind(null,tokenTypes.T_SUB),
};

const infixParserMap = {
    [tokenTypes.T_LPT]:{parser:funCall,precedence:precedenceList.call},
    [tokenTypes.T_QST]:{parser:condition,precedence:precedenceList.condition},//三元表达式

    [tokenTypes.T_ASSIGN]:{parser:assign,precedence:precedenceList.assign},//= 赋值符

    [tokenTypes.T_AND]:{parser:infix.bind(null,precedenceList.and),precedence:precedenceList.and},
    [tokenTypes.T_OR]:{parser:infix.bind(null,precedenceList.and),precedence:precedenceList.and},
    [tokenTypes.T_ADD]:{parser:infix.bind(null,precedenceList.sum),precedence:precedenceList.sum},
    [tokenTypes.T_SUB]:{parser:infix.bind(null,precedenceList.sum),precedence:precedenceList.sum},

    [tokenTypes.T_GT]:{parser:infix.bind(null,precedenceList.compare),precedence:precedenceList.compare},
    [tokenTypes.T_GE]:{parser:infix.bind(null,precedenceList.compare),precedence:precedenceList.compare},
    ...
};

表达式解析核心实现,使用普拉特分析法(也是递归下降分析法的一种

function parseExpression(precedenceValue) {
    let {token} = gData;

    //获取当前token对应的前缀解析函数
    let prefixParser = prefixParserMap[token.type];

    if(!prefixParser){
        errPrint(`unknown token : ${token.value}(${token.type})`)
    }

    let left = prefixParser();//执行解析函数
    scan();
    if(token.type === tokenTypes.T_SEMI
        || token.type === tokenTypes.T_RPT
        || token.type === tokenTypes.T_EOF
        || token.type === tokenTypes.T_COMMA
        || token.type === tokenTypes.T_COL
        || token.type === tokenTypes.T_RMBR
    ){
        return left;
    }
    let value = getPrecedence();//获取当前运算符的优先级
    while (value>precedenceValue){
// 如果当前运算符的优先大于之前的优先级,就继续向下解析
// 例如1+6*7,很明显 * 的优先级是大于 + 的,所以我们先解析 6 * 7再回去解析前面的
        let type = token.type;
        if(token.type === tokenTypes.T_SEMI
            || token.type === tokenTypes.T_RPT
            || token.type === tokenTypes.T_EOF
            || token.type === tokenTypes.T_COMMA
            || token.type === tokenTypes.T_RMBR
        ){
            return left;
        }
        let infix = infixParserMap[type]; 
        scan();
        left = infix.parser(left,type);

        if(infixParserMap[token.type]){
            value = getPrecedence();
        }
    }

    return left;
}

关于普拉特解析法,特别推荐这位大佬写的关于普拉特介绍 https://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/

3 解释执行AST

将前一步得到的AST语法树通过前序遍历,挨个节点执行,求值,一个简单的解释器就这么搞定了。

function interpretAST(astNode,result=null,scope){
    ...

    let leftResult,rightResult;
    if(astNode.left){
        leftResult = interpretAST(astNode.left,null,scope);
    }
    if(astNode.right){
        rightResult = interpretAST(astNode.right,leftResult,scope);
    }

    ...

    switch (astNode.op) {
        case ASTNodeTypes.T_VAR:
            scope.add(astNode.value);
            return;
        case ASTNodeTypes.T_INT:
            return astNode.value;
        case ASTNodeTypes.T_STRING:
            return astNode.value;
        case ASTNodeTypes.T_ADD:
            if(rightResult === null || typeof rightResult === "undefined"){
                return leftResult;
            }
            return leftResult + rightResult;
        case ASTNodeTypes.T_SUB:
            if(rightResult === null || typeof rightResult === "undefined"){
                return -leftResult;
            }
            return leftResult - rightResult;
        case ASTNodeTypes.T_MUL:
            return leftResult * rightResult;
        case ASTNodeTypes.T_DIV:
            return leftResult / rightResult;
        case ASTNodeTypes.T_ASSIGN:
            return rightResult;
        case ASTNodeTypes.T_IDENT:
            return findVar(astNode.value,scope);
        case ASTNodeTypes.T_GE:
            return  leftResult >= rightResult;
        case ASTNodeTypes.T_GT:
            return  leftResult > rightResult;
        ...

最后

完毕,有兴趣的同学可以到我的github 仓库上查看完整的实现 https://github.com/zuluoaaa/makeJs

写的可能不是很好,如有错误,请指出。

created time in a month

push eventzuluoaaa/makeJs

wzb

commit sha df4cd6660fbac433e88611e4f383580b73dd0b32

Add demo gif

view details

wzb

commit sha 3bc04d49aa88745a8798b759d40f0823e5889146

Merge remote-tracking branch 'origin/master'

view details

push time in a month

fork zuluoaaa/jsjs

简易的 JavaScript 元循环解释器

fork in a month

push eventzuluoaaa/makeJs

WuZhanBang

commit sha 456a112c0679a57b3dd9e5586b2729bcff391d2d

Update README.md

view details

push time in a month

push eventzuluoaaa/makeJs

wzb

commit sha 483ab697a504a0a92063d35eb5a76c61b5b3e5c0

Add buildInFn and deleted console code; Fix some bugs

view details

push time in a month

push eventzuluoaaa/makeJs

wzb

commit sha 5c0d2c674ce25b292b8bd31e4bcce4b05182137a

Add tests and edit readme

view details

push time in a month

push eventzuluoaaa/makeJs

wzb

commit sha d7034c56d399cde279c820989df6bc32d4a3dc57

add more condition and deleted some code

view details

push time in a month

push eventzuluoaaa/makeJs

wzb

commit sha de21306deede8c91447fff38c568192968279b58

improve tests code

view details

push time in a month

push eventzuluoaaa/makeJs

wzb

commit sha a4a69a2e45047cde00c6e2ca82a613b04436de65

Interpreter array of AST; Add method to run all tests;

view details

push time in a month

push eventzuluoaaa/makeJs

wzb

commit sha ada386c5bb57685d25df97a1cc52a48ba46c8bee

Interpret array AST

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha 49d6743f11fb6b73b1f5f81101b1b510a6721a68

add array of AST node

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha bfd33c199f5354c32906f998822198722b14cfa5

rename some file and remove console.log

view details

wzb

commit sha 5093cc2f8bdde6c38b86df9a9cd6d9ed12adcddd

Deleted some redundant codes

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha e19b545d66b82c2fff08bb7e8f2fab3149eca590

Add String type

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha 7ab5ca7c36b32eea052f273abd30a5887c8e3f2f

fix some bugs

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha 9c904c1c3dcf6737f6cdea37ef3ada3aef737a83

Support pre expr and "expr ? expr : expr"

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha d8b4e480a38a66f5b1412d6c1fec35844c62fde3

interpret function ASTNode and scope

view details

push time in 2 months

startedzuluoaaa/makeJs

started time in 2 months

startedzuluoaaa/makeJs

started time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha cc6200ecfd04ea53f5fa35c84f14576ae09965f4

Refactor codes of expression , now support most expression

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha e65c21009ef56058d433b0b3f0b0ea0274aede5d

add return statement and fix bugs of fun arg

view details

wzb

commit sha 84c6b314fdfda2d8b5d8de5a7e2c15fb69a6206f

fix bugs

view details

push time in 2 months

startedmunificent/bantam

started time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha c3c0c717722531455e3656f783c262c1c780298b

refactor codes of scope

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha 09b9b2806ad88cc23e8bbc8b62e05105ed7641b8

Fix bugs of scope

view details

push time in 2 months

startedrobertkrimen/otto

started time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha e4a399b6fc9eda19ff4ee72d800e9211c4749a42

edit README

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha 52095671f5acfc0c8351ab9d9a105ae15a051efc

fix some bugs

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha 8ed6593c6621fc2074578dd0533768124830b94e

gen AST node of function and some complex expr

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha d613d0eb2d6599f29d5c96fd11b01918af509f0b

add function types

view details

push time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha fe2902678e899191430d70b7974138a5b3d7a37e

refactor scope and add some token defines

view details

push time in 2 months

startedtc39/test262

started time in 2 months

push eventzuluoaaa/makeJs

wzb

commit sha ab22c7106aeb1e55e7a5e2b4f4666da0bf1dc127

fix Typo in readme

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 5673046ebd8d17e974b6be4a6796b8c8693db72f

add token of function

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha ab5d16bb29a5b606e1f39eb34afebc63573f1f21

add while loop

view details

push time in 3 months

startedviraptor/reverse-interview

started time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 4fcef9da5258f4b6e8252c114da541a461a000fe

finished some todo item and fix some bugs

view details

push time in 3 months

push eventzuluoaaa/makeJs

WuZhanBang

commit sha c95973e31ed75adc0948a32340ba4062da88535a

Update README.md

view details

push time in 3 months

push eventzuluoaaa/makeJs

WuZhanBang

commit sha 5727f9b139b42df0a11ab318d41a8e88bcfcc30a

Update README.md

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 664667655f70be0489e9b338a5e8746b38e48ce5

add if statement ~

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 99034d97e1a3d1f79059d7b8421aa7f1161aec82

add compare syntax and start write if statement

view details

wzb

commit sha 40516f6787f2207ba521fde3e89dfeef655bd635

Merge remote-tracking branch 'origin/master'

view details

push time in 3 months

push eventzuluoaaa/makeJs

WuZhanBang

commit sha a31a197f76408ffb85dcd2dc222dbd132dc04b2c

Update README.md

view details

push time in 3 months

push eventzuluoaaa/makeJs

WuZhanBang

commit sha 126fc80f84154fe7525956380555745bc8c10240

Update README.md

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha f9d647ef4feb0ad010d0e33550adb44e9309ca63

edit output

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha c783a131584037185ecf7c8b28f5243079926f60

edit README, rename file, add AST node types

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 1cf4b62be2c4512147f1b916ccfda47ecb9f6372

add some compare syntax

view details

push time in 3 months

PR opened DoctorWkt/acwj

Fix:Typo in part 10
+1 -1

0 comment

1 changed file

pr created time in 3 months

push eventzuluoaaa/acwj

wzb

commit sha 9bd93623ea1ef6b66b880c857d661b975a53b38c

Fix:Typo in part 10

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 1772f08976012695a6701a4e904139d3338b7c6a

feat:gen AST

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 46d89636bd5dc598f854b6a9726c4cd76901c39d

feat:start write AST

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha d7dd591ecedee16f92540b978bc8807fb1921954

feat:scan is done

view details

push time in 3 months

push eventzuluoaaa/makeJs

wzb

commit sha 2efdd3d1a96a2901052a4dd515627a2aa676d1dc

feat:defines structure and function

view details

push time in 3 months

PR opened DoctorWkt/acwj

Fix:Tiny Typo in part 4
+1 -1

0 comment

1 changed file

pr created time in 3 months

push eventzuluoaaa/acwj

wzb

commit sha 9981eb2ab3bb953db15246ab092eb06f3368bb38

Fix:Tiny Typo in part 4

view details

push time in 3 months

fork zuluoaaa/acwj

A Compiler Writing Journey

fork in 3 months

create barnchzuluoaaa/makeJs

branch : master

created branch time in 3 months

created repositoryzuluoaaa/makeJs

a Javascript compiler for compiling itself

created time in 3 months

more