Skip to content

Commit fa76ace

Browse files
committed
Initial commit with slang as-is from sabre
0 parents  commit fa76ace

20 files changed

+1901
-0
lines changed

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
8+
# Test binary, build with `go test -c`
9+
*.test
10+
11+
# Output of the go coverage tool, specifically when used with LiteIDE
12+
*.out
13+
bin/
14+
.vscode/
15+
.idea/
16+
expt/
17+
sabre.iml
18+
temp.lisp

.goreleaser.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
before:
2+
hooks:
3+
- go mod tidy
4+
- go mod download
5+
6+
builds:
7+
- main: ./cmd/slang/
8+
goos:
9+
- linux
10+
- darwin
11+
- windows
12+
goarch:
13+
- amd64
14+
- 386
15+
- arm64
16+
- arm
17+
goarm:
18+
- 5
19+
- 6
20+
- 7
21+
ignore:
22+
- goos: darwin
23+
goarch: arm
24+
- goos: darwin
25+
goarch: arm64
26+
- goos: windows
27+
goarch: arm
28+
- goos: windows
29+
goarch: arm64
30+
31+
archives:
32+
- replacements:
33+
darwin: MacOS
34+
linux: Linux
35+
windows: Windows
36+
386: i386
37+
amd64: x86_64
38+
format: zip
39+
files:
40+
- LICENSE*
41+
- README.md
42+
- CHANGELOG*
43+
- ./lib/
44+
45+
checksum:
46+
name_template: 'checksums.txt'
47+
algorithm: sha256
48+
49+
changelog:
50+
sort: asc
51+
filters:
52+
exclude:
53+
- '^docs:'
54+
- '^test:'

.travis.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
language: go
2+
go: '1.13'
3+
env:
4+
- GO111MODULE=on
5+
script: make clean test-verbose build
6+
deploy:
7+
- provider: script
8+
skip_cleanup: true
9+
script: curl -sL https://git.io/goreleaser | bash -s -- --rm-dist --skip-validate
10+
on:
11+
tags: true
12+
notifications:
13+
email: false

CHANGELOG.md

Whitespace-only changes.

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
VERSION="`git describe --abbrev=0 --tags`"
2+
COMMIT="`git rev-list -1 --abbrev-commit HEAD`"
3+
4+
all: clean fmt test build
5+
6+
fmt:
7+
@echo "Formatting..."
8+
@goimports -l -w ./
9+
10+
install:
11+
@echo "Installing slang to GOBIN..."
12+
@go install -ldflags="-X main.version=${VERSION} -X main.commit=${COMMIT}" ./cmd/slang/
13+
14+
clean:
15+
@echo "Cleaning up..."
16+
@rm -rf ./bin
17+
@go mod tidy -v
18+
19+
test:
20+
@echo "Running tests..."
21+
@go test -cover ./...
22+
23+
test-verbose:
24+
@echo "Running tests..."
25+
@go test -v -cover ./...
26+
27+
benchmark:
28+
@echo "Running benchmarks..."
29+
@go test -benchmem -run="none" -bench="Benchmark.*" -v ./...
30+
31+
build:
32+
@echo "Building..."
33+
@mkdir -p ./bin
34+
@go build -ldflags="-X main.version=${VERSION} -X main.commit=${COMMIT}" -o ./bin/slang ./cmd/slang/

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Slang
2+
3+
Slang (short for Sabre Lang) is a tiny LISP built using [Sabre](https://github.com/spy16/sabre).
4+
5+
## Installation
6+
7+
1. Download a release from [Releases](https://github.com/spy16/slang/releases) for
8+
your target platfomr.
9+
2. Extract files and add extraction path to `PATH` variable.
10+
11+
## Usage
12+
13+
1. `slang` for REPL
14+
2. `slang -e "(+ 1 2 3)"` for executing string
15+
3. `slang -f "examples/simple.lisp"` for executing file.
16+
17+
> If you specify both -f and -e flags, file will be executed first and then the string
18+
> will be executed in the same scope and you will be dropped into REPL. If REPL not needed,
19+
> use -norepl option.

bind.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package slang
2+
3+
import (
4+
"github.com/spy16/sabre"
5+
)
6+
7+
// BindAll binds all core functions into the given scope.
8+
func BindAll(scope sabre.Scope) error {
9+
core := map[string]sabre.Value{
10+
"core/->": &sabre.Fn{
11+
Args: []string{"exprs"},
12+
Func: ThreadFirst,
13+
Variadic: true,
14+
},
15+
"core/->>": &sabre.Fn{
16+
Args: []string{"exprs"},
17+
Func: ThreadLast,
18+
Variadic: true,
19+
},
20+
"core/assert": &sabre.Fn{
21+
Func: Assert,
22+
Args: []string{"expr", "err?"},
23+
Variadic: true,
24+
},
25+
"core/.": &sabre.Fn{
26+
Func: sabre.Dot,
27+
},
28+
29+
// special forms
30+
"core/do": sabre.Do,
31+
"core/def": sabre.Def,
32+
"core/if": sabre.If,
33+
"core/fn*": sabre.Lambda,
34+
"core/macro*": sabre.Macro,
35+
"core/let*": sabre.Let,
36+
"core/quote": sabre.SimpleQuote,
37+
"core/syntax-quote": sabre.SyntaxQuote,
38+
39+
"core/eval": sabre.ValueOf(sabre.Eval),
40+
"core/type": sabre.ValueOf(TypeOf),
41+
"core/to-type": sabre.ValueOf(ToType),
42+
"core/impl?": sabre.ValueOf(Implements),
43+
"core/realize": sabre.ValueOf(Realize),
44+
"core/apply-seq": sabre.ValueOf(ApplySeq),
45+
"core/throw": sabre.ValueOf(Throw),
46+
47+
// Sequence functions
48+
"core/next": sabre.ValueOf(Next),
49+
"core/first": sabre.ValueOf(First),
50+
"core/cons": sabre.ValueOf(Cons),
51+
"core/conj": sabre.ValueOf(Conj),
52+
"core/concat": sabre.ValueOf(Concat),
53+
54+
// Type system functions
55+
"core/str": sabre.ValueOf(MakeString),
56+
57+
// Math functions
58+
"core/+": sabre.ValueOf(Add),
59+
"core/-": sabre.ValueOf(Sub),
60+
"core/*": sabre.ValueOf(Multiply),
61+
"core//": sabre.ValueOf(Divide),
62+
"core/=": sabre.ValueOf(sabre.Compare),
63+
"core/>": sabre.ValueOf(Gt),
64+
"core/>=": sabre.ValueOf(GtE),
65+
"core/<": sabre.ValueOf(Lt),
66+
"core/<=": sabre.ValueOf(LtE),
67+
68+
// io functions
69+
"core/println": sabre.ValueOf(Println),
70+
"core/printf": sabre.ValueOf(Printf),
71+
72+
"types/Seq": TypeOf((*sabre.Seq)(nil)),
73+
"types/Invokable": TypeOf((*sabre.Invokable)(nil)),
74+
}
75+
76+
for sym, val := range core {
77+
if err := scope.Bind(sym, val); err != nil {
78+
return err
79+
}
80+
}
81+
82+
return nil
83+
}

cmd/slang/main.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"flag"
7+
"fmt"
8+
"os"
9+
"runtime"
10+
11+
"github.com/chzyer/readline"
12+
"github.com/spy16/sabre"
13+
"github.com/spy16/sabre/repl"
14+
"github.com/spy16/slang"
15+
)
16+
17+
const help = `Slang %s [Commit: %s] [Compiled with %s]
18+
Visit https://github.com/spy16/sabre for more.`
19+
20+
var (
21+
version = "N/A"
22+
commit = "N/A"
23+
24+
executeFile = flag.String("f", "", "File to read and execute")
25+
executeStr = flag.String("e", "", "Execute string")
26+
noREPL = flag.Bool("norepl", false, "Don't start REPL after executing file and string")
27+
)
28+
29+
type temp struct {
30+
Name string
31+
}
32+
33+
func (temp *temp) Foo() {
34+
fmt.Println("foo called")
35+
}
36+
37+
func main() {
38+
flag.Parse()
39+
40+
sl := slang.New()
41+
sl.BindGo("*version*", version)
42+
43+
var result sabre.Value
44+
var err error
45+
46+
if *executeFile != "" {
47+
fh, err := os.Open(*executeFile)
48+
if err != nil {
49+
fatalf("error: %v\n", err)
50+
}
51+
defer fh.Close()
52+
53+
result, err = sl.ReadEval(fh)
54+
if err != nil {
55+
fatalf("error: %v\n", err)
56+
}
57+
sl.SwitchNS(sabre.Symbol{Value: "user"})
58+
}
59+
60+
if *executeStr != "" {
61+
result, err = sl.ReadEvalStr(*executeStr)
62+
if err != nil {
63+
fatalf("error: %v\n", err)
64+
}
65+
}
66+
67+
if *noREPL {
68+
fmt.Println(result)
69+
return
70+
}
71+
72+
lr, errMapper := readlineInstance()
73+
74+
repl := repl.New(sl,
75+
repl.WithBanner(fmt.Sprintf(help, version, commit, runtime.Version())),
76+
repl.WithInput(lr, errMapper),
77+
repl.WithOutput(lr.Stdout()),
78+
repl.WithPrompts("=>", "|"),
79+
)
80+
81+
if err := repl.Loop(context.Background()); err != nil {
82+
fatalf("REPL exited with error: %v", err)
83+
}
84+
fmt.Println("Bye!")
85+
}
86+
87+
func readlineInstance() (*readline.Instance, func(error) error) {
88+
lr, err := readline.New("")
89+
if err != nil {
90+
fatalf("readline: %v", err)
91+
}
92+
93+
errMapper := func(e error) error {
94+
if errors.Is(e, readline.ErrInterrupt) {
95+
return nil
96+
}
97+
98+
return e
99+
}
100+
101+
return lr, errMapper
102+
}
103+
104+
func fatalf(format string, args ...interface{}) {
105+
fmt.Printf(format, args...)
106+
os.Exit(1)
107+
}

0 commit comments

Comments
 (0)