[Initial] Build: PL By: JS
来源:互联网 发布:贵阳大数据交易中心 编辑:程序博客网 时间:2024/06/06 07:31
Origin: http://lisperator.net/pltut/
This is a tutorial on how to implement a programming language.
If you ever wrote an interpreter or a compiler, then there is probably nothing new for you here.
But, if you’re using regexps to “parse” anything that looks like a programming language, then please read at least the section on parsing. Let’s write less buggy code!
The ToC on the right is in “simple-to-advanced” order. I’d recommend you not to skip forward, unless you know the subject well. You can always refer back if you don’t understand something. Also, questions and feedback are very much appreciated!
The target audience is the average JavaScript / NodeJS programmer.
What are we going to learn
- What is a parser, and how to write one.
- How to write an interpreter.
- Continuations, and why are they important.
- Writing a compiler.
- How to transform code to continuation-passing style.
- A few basic optimization techniques.
- Examples of what our λanguage brings new over plain JavaScript.
Description of the language
# this is a commentprintln("Hello World!");println(2 + 3 * 4);# functions are introduced with `lambda` or `λ`fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2);println(fib(15));print-range = λ(a, b) # `λ` is synonym to `lambda` if a <= b then { # `then` here is optional as you can see below print(a); if a + 1 <= b { print(", "); print-range(a + 1, b); } else println(""); # newline };print-range(1, 5);
Output
Hello World!146101, 2, 3, 4, 5
The λanguage looks a bit like JavaScript, but it’s different.
First, there are no statements, only expressions.
An expression returns a value and can be used in place of any other expression.
Semicolons are required to separate expressions in a “sequence”.
The curly brackets, { and }, create such a sequence, and it’s itself an expression.
Its value is what the last expression evaluates to.
The following is a valid program:
a = { fib(10); # has no side-effects, but it's computed anyway fib(15) # the last semicolon can be missing};print(a); # prints 610
Functions are introduced with one of the keywords lambda or λ (they are synonyms). After the keyword there must be a (possibly empty) parenthesized list of variable names separated with commas, like in JavaScript — these are the argument names. The function body is a single expression, but it can be a sequence wrapped in {…}. There is no return statement (there are no statements) — the last expression evaluated in a function gives the value to return to its caller.
There is no var. To introduce new variables, you can use what JavaScripters call “IIFE”. Use a lambda, declare variables as arguments. Variables have function scope, and functions are closures — like in JavaScript.
Even if is itself an expression. In JavaScript you’d get that effect with the ternary operator:
a = foo() ? bar() : baz(); // JavaScripta = if foo() then bar() else baz(); # λanguage
The then keyword is optional when the branch starts with an open bracket ({), as you can see in print-range above. Otherwise it is required. The else keyword is required if the alternative branch is present. Again, then and else take as body a single expression, but you can {group} multiple expressions by using brackets and semicolons. When the else branch is missing and the condition is false, the result of the if expression is false. Speaking of which, false is a keyword which denotes the only falsy value in our λanguage:
if foo() then print("OK");
will print “OK” if and only if the result of foo() is NOT false. There’s also a true keyword for completion, but really everything which is not false (in terms of JavaScript’s === operator) will be interpreted as true in conditionals (including the number 0 and the empty string “”).
Also note above that there is no point to demand parentheses around an if’s condition. It’s no error if you add them, though, as an open paren starts an expression — but they’re just superfluous.
A whole program is parsed as if it were embedded in curly brackets, therefore you need to place a semicolon after each expression. The last expression can be an exception.
Well, that’s our tiny λanguage. It’s not necessarily a good one. The syntax looks cute, but it has its traps. There are a lot of missing features, like objects or arrays; we don’t concentrate on them because they’re not essential for our journey. If you understand all this material, you’ll be able to implement those easily.
In the next section we’ll write a parser for this λanguage.
- [Initial] Build: PL By: JS
- [Parser] Build: PL By: JS
- [gist]Build Yourself a Backbone.js Step by Step
- Initial
- Initial
- Build JavaEE by ant
- Build Library By xcodebuild
- build.js
- Difference between release and debug build when initial a struct
- An issue caused by Initial Value in boost sparse matrix
- Oracle PL/SQL by Example
- Build URL link by GUID
- CppCMS1.0.3 Build by VS2012
- perl两个构建系统,Makefile.PL/Build.PL
- Oracle PL/SQL之GROUP BY ROLLUP
- Oracle PL/SQL之GROUP BY CUBE
- PL/SQL Step By Step(一)
- PL/SQL Step By Step(二)
- Mac系统 每次终端登录mysql都需要配置路径问题
- java的多线程安全,ReentrantLock与synchronized锁
- 【贪心】Coupons and Discounts
- 26岁学编程会不会已经晚了?
- 浅拷贝与深拷贝
- [Initial] Build: PL By: JS
- 网络 一一 HTTP 和 TCP/IP 的区别
- JAVA中的泛型(1)
- .NETCore 知识点记录-QuartzCore 定时任务
- [Unity][资源分享][精华分享]Unity官方教程素材分享
- 【每日一题(6)】Div. 64 CodeForces
- 日期的三级联动(纯js)
- 统计学习方法(第二章)感知机
- 【技术重温】html之概述