Add a port to Go

This commit is contained in:
Přemysl Eric Janouch 2018-10-09 10:37:56 +02:00
parent 55a1076367
commit f751975cfd
Signed by: p
GPG Key ID: A0420B94F92B9493
4 changed files with 1451 additions and 2 deletions

View File

@ -6,8 +6,9 @@ ell
a programming language implementable with as little code as possible while a programming language implementable with as little code as possible while
still being reasonably comfortable to use. still being reasonably comfortable to use.
This package is an implementation of said language, meant to be self-contained, This package contains two implementations of said language--one in C and
portable and reusable. Performance is specifically not an intent. another in Go--which are meant to be self-contained, portable and reusable.
Performance is specifically not an intent.
The project is currently in a "proof of concept" stage with many useful data The project is currently in a "proof of concept" stage with many useful data
operations missing but I believe it won't be a problem to implement them as operations missing but I believe it won't be a problem to implement them as

63
cmd/interpreter/main.go Normal file
View File

@ -0,0 +1,63 @@
//
// Copyright (c) 2018, Přemysl Janouch <p@janouch.name>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Program interpreter is a basic ell interpreter.
package main
import (
"fmt"
"io/ioutil"
"os"
"janouch.name/ell/ell"
)
func main() {
var script []byte
var err error
if len(os.Args) < 2 {
script, err = ioutil.ReadAll(os.Stdin)
} else {
script, err = ioutil.ReadFile(os.Args[1])
}
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
L := ell.New()
if !ell.StdInitialize(L) {
fmt.Printf("runtime library initialization failed: %s\n", L.Error)
}
program, err := ell.NewParser(script).Run()
if err != nil {
fmt.Printf("%s: %s\n", "parse error", err)
os.Exit(1)
}
var args *ell.V
tail := &args
for i := 2; i < len(os.Args); i++ {
*tail = ell.NewString([]byte(os.Args[i]))
tail = &(*tail).Next
}
var result *ell.V
if !L.EvalBlock(program, args, &result) {
fmt.Printf("%s: %s\n", "runtime error", L.Error)
}
}

91
cmd/repl/main.go Normal file
View File

@ -0,0 +1,91 @@
//
// Copyright (c) 2018, Přemysl Janouch <p@janouch.name>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Program repl is an interactive ell interpreter.
package main
import (
"fmt"
"io"
"os"
"strings"
// This library is rather simplistic but it's going to serve us fine.
"github.com/peterh/liner"
"janouch.name/ell/ell"
)
func run(L *ell.Ell, program *ell.V) {
var result *ell.V
if !L.EvalBlock(program, nil, &result) {
fmt.Printf("\x1b[31m%s: %s\x1b[0m\n", "runtime error", L.Error)
L.Error = ""
} else {
ell.PrintSeq(os.Stdout, result)
os.Stdout.WriteString("\n")
}
}
func complete(L *ell.Ell, line string) (res []string) {
// This never actually completes anything, just shows the options,
// we'd have to figure out the longest common prefix.
res = append(res, line)
line = strings.ToLower(line)
for v := L.Globals; v != nil; v = v.Next {
name := string(v.Head.String)
if strings.HasPrefix(strings.ToLower(name), line) {
res = append(res, name)
}
}
for name := range L.Native {
if strings.HasPrefix(strings.ToLower(name), line) {
res = append(res, name)
}
}
return
}
func main() {
L := ell.New()
if !ell.StdInitialize(L) {
fmt.Printf("runtime library initialization failed: %s\n", L.Error)
}
line := liner.NewLiner()
line.SetCompleter(func(line string) []string { return complete(L, line) })
line.SetMultiLineMode(true)
line.SetTabCompletionStyle(liner.TabPrints)
for {
script, err := line.Prompt("> ")
if err == nil {
line.AppendHistory(script)
p := ell.NewParser([]byte(script))
if program, err := p.Run(); err != nil {
fmt.Printf("\x1b[31m%s: %s\x1b[0m\n", "parse error", err)
} else {
run(L, program)
}
} else if err == liner.ErrPromptAborted || err == io.EOF {
break
} else {
fmt.Printf("\x1b[31m%s: %s\x1b[0m\n", "error", err)
}
}
os.Stdout.WriteString("\n")
}

1294
ell/ell.go Normal file

File diff suppressed because it is too large Load Diff