Skip to content

Commit

Permalink
Move language core out to separate Go package
Browse files Browse the repository at this point in the history
  • Loading branch information
thesephist committed Aug 8, 2019
1 parent a8326c3 commit 8431661
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 75 deletions.
10 changes: 5 additions & 5 deletions .gitignore
@@ -1,9 +1,9 @@
# Build artifacts
ink
ink-*
ink.exe
ink.exe~
ink.wasm
./ink
./ink-*
./ink.exe
./ink.exe~
./ink.wasm
*.dll
*.o
*.so
Expand Down
11 changes: 6 additions & 5 deletions Makefile
@@ -1,4 +1,5 @@
RUN = go run -race .
CMD = ./cmd/ink.go
RUN = go run -race ${CMD}
LDFLAGS = -ldflags="-s -w"

all: run test install
Expand Down Expand Up @@ -44,7 +45,7 @@ test:

# build for specific OS target
build-%:
GOOS=$* GOARCH=amd64 go build ${LDFLAGS} -o ink-$*
GOOS=$* GOARCH=amd64 go build ${LDFLAGS} -o ink-$* ${CMD}


# build for all OS targets, useful for releases
Expand All @@ -54,14 +55,14 @@ build: build-linux build-darwin build-windows build-openbsd
# install on host system
install:
cp utils/ink.vim ~/.vim/syntax/ink.vim
go install ${LDFLAGS}
go install ${LDFLAGS} ${CMD}
ls -l `which ink`


# pre-commit hook
precommit:
go vet .
go fmt .
go vet ./cmd ./pkg/ink
go fmt ./cmd ./pkg/ink


# clean any generated files
Expand Down
48 changes: 30 additions & 18 deletions README.md
Expand Up @@ -156,34 +156,46 @@ The APIs are still in development / in flux, but you can check out `main.go` and
For now, here's a minimal example of creating an execution context for Ink and running some Ink code from stdin. (In fact, this is very nearly the implementation of executing from stdin in the interpreter.)

```go
package main

import (
"github.com/thesephist/ink/pkg/ink"
)

func main() {
// Create an "Engine", which is a global execution context for the lifetime of an Ink program.
eng := Engine{}
// Create a "Context", which is a temporary execution context for a given source of input.
ctx := eng.CreateContext{}

// Execute code from an io.Reader
ctx.Exec(os.Stdin)
// Wait until all concurrent callbacks finish from the program before exiting
eng.Listeners.Wait()
// Create an "Engine", which is a global execution context for the lifetime of an Ink program.
eng := ink.Engine{}
// Create a "Context", which is a temporary execution context for a given source of input.
ctx := eng.CreateContext{}

// Execute code from an io.Reader
ctx.Exec(os.Stdin)
// Wait until all concurrent callbacks finish from the program before exiting
eng.Listeners.Wait()
}
```

To run from a file, use `os.File` as an `io.Reader`.

```go
package main

import (
"github.com/thesephist/ink/pkg/ink"
)

func main() {
eng := Engine{}
ctx := eng.CreateContext{}
eng := ink.Engine{}
ctx := eng.CreateContext{}

file, err := os.Open("main.ink")
defer file.Close()
if err != nil {
log.Fatal("Could not open main.ink for execution")
}
file, err := os.Open("main.ink")
defer file.Close()
if err != nil {
log.Fatal("Could not open main.ink for execution")
}

ctx.Exec(file)
eng.Listeners.Wait()
ctx.Exec(file)
eng.Listeners.Wait()
}
```

Expand Down
17 changes: 11 additions & 6 deletions main.go → cmd/ink.go
Expand Up @@ -8,6 +8,8 @@ import (
"os"
"path"
"strings"

"github.com/thesephist/ink/pkg/ink"
)

const VERSION = "0.1.5"
Expand Down Expand Up @@ -67,14 +69,14 @@ func main() {
}

// execution environment
eng := Engine{
eng := ink.Engine{
FatalError: false,
Permissions: PermissionsConfig{
Permissions: ink.PermissionsConfig{
Read: !*noRead && !*isolate,
Write: !*noWrite && !*isolate,
Net: !*noNet && !*isolate,
},
Debug: DebugConfig{
Debug: ink.DebugConfig{
Lex: *debugLexer || *verbose,
Parse: *debugParser || *verbose,
Dump: *dump || *verbose,
Expand All @@ -90,13 +92,16 @@ func main() {
replLoop:
for {
// green arrow
fmt.Printf(ANSI_GREEN_BOLD + "> " + ANSI_RESET)
fmt.Printf(ink.ANSI_GREEN_BOLD + "> " + ink.ANSI_RESET)
text, err := reader.ReadString('\n')

if err == io.EOF {
break
} else if err != nil {
logErrf(ErrSystem, "unexpected end to input:\n\t-> %s", err.Error())
ink.LogErrf(
ink.ErrSystem,
"unexpected end to input:\n\t-> %s", err.Error(),
)
}

switch {
Expand All @@ -112,7 +117,7 @@ func main() {
default:
val, _ := ctx.Exec(strings.NewReader(text))
if val != nil {
logInteractive(val.String())
ink.LogInteractive(val.String())
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion error.go → pkg/ink/error.go
@@ -1,4 +1,4 @@
package main
package ink

// Error reasons are enumerated here to be used in the Err struct,
// the error type shared across all Ink APIs.
Expand Down
24 changes: 12 additions & 12 deletions eval.go → pkg/ink/eval.go
@@ -1,4 +1,4 @@
package main
package ink

import (
"bytes"
Expand Down Expand Up @@ -267,7 +267,7 @@ func (n UnaryExprNode) Eval(frame *StackFrame, allowThunk bool) (Value, error) {
}
}

logErrf(ErrAssert, "unrecognized unary operator %s", n)
LogErrf(ErrAssert, "unrecognized unary operator %s", n)
return nil, nil
}

Expand Down Expand Up @@ -670,7 +670,7 @@ func (n BinaryExprNode) Eval(frame *StackFrame, allowThunk bool) (Value, error)
return BooleanValue(leftValue.Equals(rightValue)), nil
}

logErrf(ErrAssert, "unknown binary operator %s", n.String())
LogErrf(ErrAssert, "unknown binary operator %s", n.String())
return nil, err
}

Expand Down Expand Up @@ -725,7 +725,7 @@ func evalInkFunction(fn Value, allowThunk bool, args ...Value) (Value, error) {
}

func (n MatchClauseNode) Eval(frame *StackFrame, allowThunk bool) (Value, error) {
logErrf(ErrAssert, "cannot Eval a MatchClauseNode")
LogErrf(ErrAssert, "cannot Eval a MatchClauseNode")
return nil, nil
}

Expand Down Expand Up @@ -823,7 +823,7 @@ func (n ObjectLiteralNode) Eval(frame *StackFrame, allowThunk bool) (Value, erro
}

func (n ObjectEntryNode) Eval(frame *StackFrame, allowThunk bool) (Value, error) {
logErrf(ErrAssert, "cannot Eval an ObjectEntryNode")
LogErrf(ErrAssert, "cannot Eval an ObjectEntryNode")
return nil, nil
}

Expand Down Expand Up @@ -889,7 +889,7 @@ func (frame *StackFrame) Up(name string, val Value) {
frame = frame.parent
}

logErrf(
LogErrf(
ErrAssert,
fmt.Sprintf("StackFrame.Up expected to find variable '%s' in frame but did not",
name),
Expand Down Expand Up @@ -961,9 +961,9 @@ func (ctx *Context) LogErr(e Err) {
}

if ctx.Engine.FatalError {
logErr(e.reason, msg)
LogErr(e.reason, msg)
} else {
logSafeErr(e.reason, msg)
LogSafeErr(e.reason, msg)
}
}

Expand All @@ -984,14 +984,14 @@ type DebugConfig struct {

// Dump prints the current state of the Context's global heap
func (ctx *Context) Dump() {
logDebug("frame dump ->", ctx.Frame.String())
LogDebug("frame dump ->", ctx.Frame.String())
}

func (ctx *Context) resetWd() {
var err error
ctx.Cwd, err = os.Getwd()
if err != nil {
logErrf(
LogErrf(
ErrSystem,
"could not identify current working directory\n\t-> %s", err,
)
Expand Down Expand Up @@ -1053,7 +1053,7 @@ func (ctx *Context) Exec(input io.Reader) (Value, error) {
// ExecPath is a convenience function to Exec() a program file in a given Context.
func (ctx *Context) ExecPath(filePath string) {
if !path.IsAbs(filePath) {
logErrf(
LogErrf(
ErrAssert,
"Context.ExecPath expected an absolute path, got something else",
)
Expand All @@ -1066,7 +1066,7 @@ func (ctx *Context) ExecPath(filePath string) {
file, err := os.Open(filePath)
defer file.Close()
if err != nil {
logSafeErr(
LogSafeErr(
ErrSystem,
fmt.Sprintf("could not open %s for execution:\n\t-> %s", filePath, err),
)
Expand Down
8 changes: 4 additions & 4 deletions lexer.go → pkg/ink/lexer.go
@@ -1,4 +1,4 @@
package main
package ink

import (
"bufio"
Expand Down Expand Up @@ -127,7 +127,7 @@ func Tokenize(
simpleCommit := func(tok Tok) {
lastKind = tok.kind
if debugLexer {
logDebug("lex ->", tok.String())
LogDebug("lex ->", tok.String())
}
tokens <- tok
}
Expand Down Expand Up @@ -156,9 +156,9 @@ func Tokenize(
lineNo, colNo, err.Error()),
}
if fatalError {
logErr(e.reason, e.message)
LogErr(e.reason, e.message)
} else {
logSafeErr(e.reason, e.message)
LogSafeErr(e.reason, e.message)
}
}
simpleCommit(Tok{
Expand Down
24 changes: 12 additions & 12 deletions log.go → pkg/ink/log.go
@@ -1,4 +1,4 @@
package main
package ink

import (
"fmt"
Expand All @@ -18,23 +18,23 @@ const (
ANSI_RED_BOLD = ""
)

func logDebug(args ...string) {
func LogDebug(args ...string) {
fmt.Println(ANSI_BLUE_BOLD + "debug: " + ANSI_BLUE + strings.Join(args, " ") + ANSI_RESET)
}

func logDebugf(s string, args ...interface{}) {
logDebug(fmt.Sprintf(s, args...))
func LogDebugf(s string, args ...interface{}) {
LogDebug(fmt.Sprintf(s, args...))
}

func logInteractive(args ...string) {
func LogInteractive(args ...string) {
fmt.Println(ANSI_GREEN + strings.Join(args, " ") + ANSI_RESET)
}

func logInteractivef(s string, args ...interface{}) {
logInteractive(fmt.Sprintf(s, args...))
func LogInteractivef(s string, args ...interface{}) {
LogInteractive(fmt.Sprintf(s, args...))
}

func logSafeErr(reason int, args ...string) {
func LogSafeErr(reason int, args ...string) {
errStr := "error"
switch reason {
case ErrSyntax:
Expand All @@ -51,11 +51,11 @@ func logSafeErr(reason int, args ...string) {
fmt.Fprintln(os.Stderr, ANSI_RED_BOLD+errStr+": "+ANSI_RED+strings.Join(args, " ")+ANSI_RESET)
}

func logErr(reason int, args ...string) {
logSafeErr(reason, args...)
func LogErr(reason int, args ...string) {
LogSafeErr(reason, args...)
os.Exit(reason)
}

func logErrf(reason int, s string, args ...interface{}) {
logErr(reason, fmt.Sprintf(s, args...))
func LogErrf(reason int, s string, args ...interface{}) {
LogErr(reason, fmt.Sprintf(s, args...))
}
10 changes: 5 additions & 5 deletions parser.go → pkg/ink/parser.go
@@ -1,4 +1,4 @@
package main
package ink

import (
"fmt"
Expand Down Expand Up @@ -289,19 +289,19 @@ func Parse(
e, isErr := err.(Err)
if isErr {
if fatalError {
logErr(e.reason, e.message)
LogErr(e.reason, e.message)
} else {
logSafeErr(e.reason, e.message)
LogSafeErr(e.reason, e.message)
}
} else {
logErrf(ErrAssert, "err raised that was not of Err type -> %s",
LogErrf(ErrAssert, "err raised that was not of Err type -> %s",
err.Error())
}
return
}

if debugParser {
logDebug("parse ->", expr.String())
LogDebug("parse ->", expr.String())
}
nodes <- expr
}
Expand Down
4 changes: 2 additions & 2 deletions runtime.go → pkg/ink/runtime.go
@@ -1,4 +1,4 @@
package main
package ink

import (
"bufio"
Expand Down Expand Up @@ -1090,7 +1090,7 @@ func inkWait(ctx *Context, in []Value) (Value, error) {
if e, isErr := err.(Err); isErr {
ctx.LogErr(e)
} else {
logErrf(ErrAssert, "Eval of an Ink node returned error not of type Err")
LogErrf(ErrAssert, "Eval of an Ink node returned error not of type Err")
}
}
})
Expand Down

0 comments on commit 8431661

Please sign in to comment.