Skip to content

Commit aad3035

Browse files
committed
chapter A self-hosting (wip)
1 parent fae89bc commit aad3035

File tree

4 files changed

+76
-5
lines changed

4 files changed

+76
-5
lines changed

hello.lisp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; run with: `rlwrap go run *.go hello.lisp` or `rlwrap go run *.go hello.lisp World`
2+
3+
(def greet
4+
(fn (name)
5+
(def repeat (not (bool name)))
6+
(set name (or name (readLine "Name: ")))
7+
(if (= "" name)
8+
(set repeat :false)
9+
(println "Hello, " name "!"))
10+
(if repeat (greet :nil) :nil)))
11+
12+
(if (isEmpty osArgs)
13+
(greet :nil)
14+
(map greet osArgs))

interp.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55
"fmt"
66
)
77

8-
const disableTracing = true
9-
const disableTcoFuncs = false // caution: cannot def `macro`s if `true`; setting is just for quick temporary via-REPL trouble-shootings to see if TCO got somehow broken.
8+
const disableTcoFuncs = false // caution: if `true`, cannot def `macro`s; this bool is just for quick temporary via-REPL trouble-shootings to see if TCO got somehow broken (or to enable call tracing for trouble-shooting)
9+
const disableTracing = true || !disableTcoFuncs
1010

11-
// to confirm TCO still works, uncomment the 2 commented lines in `evalAndApply` below.
11+
// to confirm TCO still works, uncomment the 2 commented lines in `evalAndApply` below that are referring to `id`.
1212
// another way: run `(sum2 10000000 0)` with TCO disabled (stack overflow) and then re-enabled (no stack overflow), where `sum2` is in github.com/kanaka/mal/blob/master/impls/tests/step5_tco.mal
1313

1414
func evalAndApply(env *Env, expr Expr) (Expr, error) {

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const srcMiniStdlibMacros = `
114114
115115
(def or
116116
(macro (any1 any2)
117-
´(if ~any1 :true ~any2)))
117+
´(if ~any1 ~any1 ~any2)))
118118
119119
(def postfix ;;; turns (1 2 +) into (+ 1 2)
120120
(macro (call)

std.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"errors"
45
"fmt"
56
"io"
67
"os"
@@ -57,6 +58,9 @@ var (
5758
"quit": ExprFunc(stdQuit),
5859
"exit": ExprFunc(stdQuit),
5960
"time-ms": ExprFunc(stdTimeMs),
61+
"bool": ExprFunc(stdBool),
62+
"seq": ExprFunc(stdSeq),
63+
"conj": ExprFunc(stdConj),
6064
}}
6165
)
6266

@@ -205,12 +209,22 @@ func stdIs(args []Expr) (Expr, error) {
205209
if _, ok = args[1].(*ExprFn); !ok {
206210
_, ok = args[1].(ExprFunc)
207211
}
212+
case ":macro":
213+
if fn, _ := args[1].(*ExprFn); fn != nil {
214+
ok = fn.isMacro
215+
}
208216
case ":err":
209217
_, ok = args[1].(ExprErr)
210218
case ":atom":
211219
_, ok = args[1].(*ExprAtom)
220+
case ":nil":
221+
ok = (isEq(exprNil, args[1]))
222+
case ":true":
223+
ok = (isEq(exprTrue, args[1]))
224+
case ":false":
225+
ok = (isEq(exprFalse, args[1]))
212226
default:
213-
return nil, fmt.Errorf("expected not `%s` but one of: `:list`, `:ident`, `:str`, `:num`, `:vec`, `:hashmap`, `:fn`, `:keyword`, `:atom`, `:err`", kind)
227+
return nil, fmt.Errorf("expected not `%s` but one of: `:list`, `:ident`, `:str`, `:num`, `:vec`, `:hashmap`, `:fn`, `:macro`, `:keyword`, `:atom`, `:err`, `:nil`, `:true`, `:false`", kind)
214228
}
215229
return exprBool(ok), nil
216230
}
@@ -662,3 +676,46 @@ func stdQuit(args []Expr) (Expr, error) {
662676
func stdTimeMs(args []Expr) (Expr, error) {
663677
return ExprNum(time.Now().UnixMilli()), nil
664678
}
679+
680+
func stdBool(args []Expr) (Expr, error) {
681+
if err := checkArgsCount(1, 1, args); err != nil {
682+
return nil, err
683+
}
684+
return exprBool((!isEq(exprFalse, args[0])) && !isEq(exprNil, args[0])), nil
685+
}
686+
687+
func stdSeq(args []Expr) (Expr, error) {
688+
if err := checkArgsCount(1, 1, args); err != nil {
689+
return nil, err
690+
}
691+
if isEq(exprNil, args[0]) {
692+
return args[0], nil
693+
}
694+
switch it := args[0].(type) {
695+
case ExprList:
696+
if len(it) == 0 {
697+
return exprNil, nil
698+
}
699+
return it, nil
700+
case ExprVec:
701+
if len(it) == 0 {
702+
return exprNil, nil
703+
}
704+
return (ExprList)(it), nil
705+
case ExprStr:
706+
if len(it) == 0 {
707+
return exprNil, nil
708+
}
709+
expr := make(ExprList, 0, len(it))
710+
for _, char := range it {
711+
expr = append(expr, ExprStr(char))
712+
}
713+
return expr, nil
714+
}
715+
716+
return nil, fmt.Errorf("expected a list, vector, string or :nil instead of `%s`", str(true, args[0]))
717+
}
718+
719+
func stdConj(args []Expr) (Expr, error) {
720+
return nil, errors.New("TODO")
721+
}

0 commit comments

Comments
 (0)