Skip to content
This repository was archived by the owner on Feb 11, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ written in the host language which starts a Prybar-compatible REPL.
| Ruby 2.5 | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ |
| SQLite | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ |
| Tcl | ✔ | ✔ | ✔ | ✗ | ✗ | - |
| Hoon | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ |

## Start to Develop with Nix

Expand Down
5 changes: 4 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
inherit (self.packages.${prev.system})
prybar-R prybar-clojure prybar-elisp prybar-julia prybar-lua prybar-nodejs
prybar-ocaml prybar-python2 prybar-python3 prybar-python310 prybar-ruby
prybar-scala prybar-sqlite prybar-tcl;
prybar-scala prybar-sqlite prybar-tcl prybar-hoon;
};
};
} //
Expand Down Expand Up @@ -104,6 +104,8 @@

prybar-scala = buildPrybar { language = "scala"; };

prybar-hoon = buildPrybar { language = "hoon"; };

prybar-sqlite = buildPrybar {
language = "sqlite";
binaries = [ pkgs.sqlite ];
Expand Down Expand Up @@ -160,6 +162,7 @@
pkgs.sqlite
pkgs.tcl
pkgs.expect
pkgs.urbit
];
shellHook = ''
export CGO_LDFLAGS_ALLOW="-Wl,--compress-debug-sections=zlib"
Expand Down
147 changes: 147 additions & 0 deletions languages/hoon/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package main

// USING_CGO

import (
"github.com/chzyer/readline"

"fmt"
"io"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
)

type Hoon struct {
ps1 string
ps2 string
}

func (p Hoon) Open() {
}

func (p Hoon) SetPrompts(ps1, ps2 string) {
p.ps1 = ps1
p.ps2 = ps2
}

func GetPath() string {
pat, err := exec.LookPath("urbit")
if err != nil {
panic(err)
}
return pat
}

func (p Hoon) Version() string {
urb := exec.Command(GetPath(), "--version")
versions, err := urb.Output()
if err != nil {
panic(err)
}

return string(versions)
}

func (p Hoon) EvalFile(file string, args []string) int {
fileContents, err := os.ReadFile(file)
if err != nil {
panic(err)
}
out, _, err := RunCommand(string(fileContents))
if err != nil {
panic(err)
}

fmt.Println(string(out))

return 0
}

func RunCommand(command string) (string, bool, error) {
urb := exec.Command(GetPath(), "eval")
stdin, err := urb.StdinPipe()
if err != nil {
return "", false, err
}
io.WriteString(stdin, command+"\n")
stdin.Close()
out, err := urb.Output()
if err != nil {
return "", false, err
}

stringOut := string(out)

lines := strings.Split(stringOut, "\n")

needsMoreInput := true
if len(lines) > 1 && len(lines[0]) == 21 {
needsMoreInput = needsMoreInput && (lines[0][11:16] == "/eval")

rxp := regexp.MustCompile(`\{(\d+) (\d+)\}`)
lineMatches := rxp.FindSubmatch([]byte(lines[1]))
if len(lineMatches) == 3 {
l, _ := strconv.Atoi(string(lineMatches[1]))
c, _ := strconv.Atoi(string(lineMatches[2]))

realL := len(strings.Split(command, "\n"))

needsMoreInput = needsMoreInput && (realL+1 == l) && (c == 1)

} else {
needsMoreInput = false
}

} else {
needsMoreInput = false
}

return stringOut, needsMoreInput, nil

}

func (p Hoon) EvalExpression(code string) string {
out, _, err := RunCommand(code)

if err != nil {
panic(err)
}

return string(out)
}

func (p Hoon) REPL() {
for {
line, err := readline.Line("--> ")
if err != nil {
break
}
readline.AddHistory(line)
out, needMoreInput, err := RunCommand(line)

for needMoreInput {
newLine, err := readline.Line("... ")
if err != nil {
break
}
readline.AddHistory(newLine)
line = line + "\n" + newLine
out, needMoreInput, err = RunCommand(line)
}

if err != nil {
panic(err)
}

strOut := string(out)
fmt.Println(strOut)
}
}

func (p Hoon) Close() {
}

var Instance = Hoon{}