Skip to content

Commit bf035dd

Browse files
committed
you can complier it to JS
1 parent 50e01f6 commit bf035dd

7 files changed

Lines changed: 87 additions & 120 deletions

File tree

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
npm install implement-a-pl
1010
```
1111

12-
## usage
12+
## syntax
1313
ref the [example](./bin/lambda)
1414

1515
## API
@@ -21,12 +21,16 @@ ref the [example](./bin/lambda)
2121
* Environment.evalute: eval ast expression with an env
2222

2323

24-
## run
24+
## run the language
2525
```
2626
bin/lambda demo
2727
```
28+
## complier the language to JS
29+
```
30+
bin/code-to-js demo2
31+
```
2832

29-
### example
33+
### example about syntax
3034

3135
```
3236
print_range = λ(a, b) if a <= b {

bin/code-to-js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env node
2+
3+
let InputStream = require('../src/InputStream')
4+
let TokenStream = require('../src/TokenStream')
5+
let parser = require('../src/parser')
6+
let makejs = require('../src/codeGen')
7+
let env = require('../index')
8+
9+
const fs = require('fs')
10+
11+
let args = process.argv
12+
13+
if(args.length === 2){
14+
throw Error('need src and target')
15+
}
16+
else if(args.length === 3){
17+
args.push('./' + args[2] + '.js')
18+
}
19+
20+
code = fs.readFileSync(args[2]).toString('utf-8')
21+
22+
ast = parser(TokenStream(InputStream(code)))
23+
let jsCode = makejs(ast)
24+
25+
fs.writeFileSync(args[3], jsCode, 'utf-8')

bin/commit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#!bash
2+
13
git add .
24
git commit -m "auto update"
35
git push

demo2

Lines changed: 1 addition & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1 @@
1-
# ref: http://lisperator.net/pltut/eval1/play
2-
3-
print_range = λ(a, b) if a <= b {
4-
println(a);
5-
if a + 1 <= b {
6-
print_range(a + 1, b);
7-
}
8-
else
9-
println("");
10-
};
11-
print_range(1, 10);
12-
13-
cons = λ(a, b) λ(f) f(a, b);
14-
car = λ(cell) cell(λ(a, b) a);
15-
cdr = λ(cell) cell(λ(a, b) b);
16-
NIL = λ(f) f(NIL, NIL);
17-
18-
x = cons(1, cons(2, cons(3, cons(4, cons(5, NIL)))));
19-
println(car(x)); # 1
20-
println(car(cdr(x))); # 2
21-
println(car(cdr(cdr(x)))); # 3
22-
println(car(cdr(cdr(cdr(x))))); # 4
23-
println(car(cdr(cdr(cdr(cdr(x)))))); # 5
24-
25-
26-
# code = fs-readFileSync("./demo");
27-
# println(code);
28-
# println(os-arch());
29-
30-
add = lambda(a, b){
31-
1;
32-
# return the last expression
33-
a + b
34-
};
35-
println(add(100, 133));
36-
37-
foreach = λ(list, f)
38-
if list != NIL {
39-
f(car(list));
40-
foreach(cdr(list), f);
41-
};
42-
foreach(x, println);
43-
44-
range = λ(a, b)
45-
if a <= b then cons(a, range(a + 1, b))
46-
else NIL;
47-
48-
# print the squares of 1..8
49-
foreach(range(1, 8), λ(x) println(x * x));
50-
51-
52-
cons = λ(x, y)
53-
λ(a, i, v)
54-
if a == "get"
55-
then if i == 0 then x else y
56-
else if i == 0 then x = v else y = v;
57-
58-
car = λ(cell) cell("get", 0);
59-
cdr = λ(cell) cell("get", 1);
60-
set-car! = λ(cell, val) cell("set", 0, val);
61-
set-cdr! = λ(cell, val) cell("set", 1, val);
62-
63-
# NIL can be a real cons this time
64-
NIL = cons(0, 0);
65-
set-car!(NIL, NIL);
66-
set-cdr!(NIL, NIL);
67-
68-
## test:
69-
x = cons(1, 2);
70-
println(car(x));
71-
println(cdr(x));
72-
set-car!(x, 10);
73-
set-cdr!(x, 20);
74-
println(car(x));
75-
println(cdr(x));
76-
77-
78-
## IIFE
79-
println(let loop (n = 100)
80-
if n > 0 then n + loop(n - 1)
81-
else 0);
82-
83-
let (x = 2, y = x + 1, z = x + y)
84-
println(x + y + z);
85-
86-
# errors out, the vars are bound to the let body
87-
# print(x + y + z);
88-
89-
let (x = 10) {
90-
let (x = x * 2, y = x * x) {
91-
println(x); ## 20
92-
println(y); ## 400
93-
};
94-
println(x); ## 10
95-
};
96-
97-
fib = λ(n) if n < 2 then n else fib(n - 1) + fib(n - 2);
98-
println(fib(22));
99-
100-
copyFile = lambda(source, dest){
101-
writeFile(dest, readFile(source))
102-
};
103-
copyFile("demo", "demo2");
104-
105-
106-
println(1 + twice(2, 3));
107-
1+
sum = lambda(x, y) x + y; print(sum(2, 3));

demo2.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
((sum=(function (x, y) {return (x+y)})),print(sum(2,3)))

index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ globalEnv.def("writeFile", function (k, filename, data) {
4242
})
4343

4444
globalEnv.def("twice", function (k, a, b) {
45-
console.log('1!!!!!', a)
45+
// console.log('1!!!!!', a)
4646
k(a)
47-
console.log('2!!!!!', b)
47+
// console.log('2!!!!!', b)
4848
k(b)
4949
})
5050

5151

52+
5253
module.exports = globalEnv

src/codeGen.js

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
let FALSE = {
2+
type: "bool",
3+
value: false
4+
}
5+
6+
17
function makejs(expr) {
28
return js(expr)
39

@@ -28,33 +34,67 @@ function makejs(expr) {
2834
}
2935
}
3036

31-
function jsAtom(expr){
37+
function jsAtom(expr) {
3238
return JSON.stringify(expr.value)
3339
}
3440

35-
function makeVar(name){
41+
function makeVar(name) {
3642
return name
3743
}
3844

39-
function jsVar(expr){
45+
function jsVar(expr) {
4046
return makeVar(expr.value)
4147
}
4248

43-
function jsBinary(expr){
49+
function jsBinary(expr) {
4450
return '(' + js(expr.left) + expr.operator + js(expr.right) + ')'
4551
}
4652

47-
function jsAssign(expr){
53+
function jsAssign(expr) {
4854
return jsBinary(expr)
4955
}
5056

51-
function jsLambda(expr){
57+
function jsLambda(expr) {
5258
let code = '(function '
53-
if(expr.name){
59+
if (expr.name) {
5460
code += makeVar(expr.name)
5561
}
5662
code += '(' + expr.vars.map(makeVar).join(', ') + ') {'
5763
code += 'return ' + js(expr.body) + '})'
5864
return code
5965
}
60-
}
66+
67+
function jsLet(expr) {
68+
if (expr.vars.length === 0) {
69+
return js(expr.body)
70+
}
71+
let iife = {
72+
type: 'call',
73+
func: {
74+
type: 'lambda',
75+
vars: [expr.vars[0].name],
76+
body: {
77+
type: 'let',
78+
vars: expr.vars.slice(1),
79+
body: expr.body
80+
}
81+
},
82+
args: [expr.vars[0].def || FALSE]
83+
}
84+
return '(' + js(iife) + ')'
85+
}
86+
87+
function jsIf(expr) {
88+
return '(' + js(expr.cond) + ' !== false' + '?' + js(expr.then) + ':' + js(expr.else || FALSE) + ')'
89+
}
90+
91+
function jsProg(expr){
92+
return '(' + expr.prog.map(js).join(',') + ')'
93+
}
94+
95+
function jsCall(expr){
96+
return js(expr.func) + '(' + expr.args.map(js).join(',') + ')'
97+
}
98+
}
99+
100+
module.exports = makejs

0 commit comments

Comments
 (0)