Got basic demo working, ran go fmt

This commit is contained in:
Brian Picciano 2021-12-30 15:29:38 -07:00
parent 6257495fe4
commit ebf57591a8
11 changed files with 131 additions and 66 deletions

View File

@ -1,37 +1,7 @@
# Ginger
Fibonacci function in ginger:
```
fib = {
decr = { out = add < (in; -1;); };
out = {
n = tupEl < (in; 0;);
a = tupEl < (in; 1;);
b = tupEl < (in; 2;);
out = if < (
zero? < n;
a;
recur < (
decr < n;
b;
add < (a;b;);
);
);
} < (in; 0; 1;);
};
```
Usage of the function to generate the 6th fibonnaci number:
```
fib < 5;
```
A programming language utilizing a graph datastructure for syntax. Currently in
super-early-alpha-don't-actually-use-this-for-anything development.
## Development
@ -48,3 +18,16 @@ from the repo root and you will be dropped into a shell with all dependencies
(including the correct go version) in your PATH, ready to use. This could
probably be expanded to other OSs/architectures easily, if you care to do so
please check out the `default.nix` file and submit a PR!
## Demo
An example program which computes the Nth fibonacci number can be found at
`examples/fib.gg`. You can try it out by doing:
```
go run ./cmd/eval/main.go "$(cat examples/fib.gg)" 5
```
Where you can replace `5` with any number. The vm has only been given enough
capability to run this program as a demo, and is extremely poorly optimized (as
will be evident if you input any large number). Further work is obviously TODO.

41
cmd/eval/main.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"bytes"
"fmt"
"os"
"github.com/mediocregopher/ginger/gg"
"github.com/mediocregopher/ginger/vm"
)
func main() {
if len(os.Args) < 3 {
fmt.Printf(`Usage: %s <operation source> "in = <value>"\n`, os.Args[0])
return
}
opSrc := os.Args[1]
inSrc := os.Args[2]
inVal, err := gg.DecodeSingleValueFromLexer(
gg.NewLexer(bytes.NewBufferString(inSrc + ";")),
)
if err != nil {
panic(fmt.Sprintf("decoding input: %v", err))
}
res, err := vm.EvaluateSource(
bytes.NewBufferString(opSrc),
inVal,
vm.GlobalScope,
)
if err != nil {
panic(fmt.Sprintf("evaluating: %v", err))
}
fmt.Println(res)
}

19
examples/fib.gg Normal file
View File

@ -0,0 +1,19 @@
out = {
decr = { out = add < (in; -1;); };
n = tupEl < (in; 0;);
a = tupEl < (in; 1;);
b = tupEl < (in; 2;);
out = if < (
isZero < n;
a;
recur < (
decr < n;
b;
add < (a;b;);
);
);
} < (in; 0; 1;);

View File

@ -291,7 +291,7 @@ func (d *decoder) parseValIn(into *Graph, toks []LexerToken) (*Graph, []LexerTok
return into.AddValueIn(dstVal, oe), toks, nil
}
func (d *decoder) decode(lexer Lexer) (*Graph, error) {
func (d *decoder) readAllTokens(lexer Lexer) ([]LexerToken, error) {
var toks []LexerToken
@ -309,6 +309,17 @@ func (d *decoder) decode(lexer Lexer) (*Graph, error) {
toks = append(toks, tok)
}
return toks, nil
}
func (d *decoder) decode(lexer Lexer) (*Graph, error) {
toks, err := d.readAllTokens(lexer)
if err != nil {
return nil, err
}
val, _, _, err := d.parseGraphValue(toks, false)
if err != nil {
@ -326,3 +337,17 @@ func DecodeLexer(lexer Lexer) (*Graph, error) {
decoder := &decoder{}
return decoder.decode(lexer)
}
func DecodeSingleValueFromLexer(lexer Lexer) (Value, error) {
decoder := &decoder{}
toks, err := decoder.readAllTokens(lexer)
if err != nil {
return ZeroValue, err
}
val, _, _, err := decoder.parseSingleValue(toks)
return val, err
}

View File

@ -284,14 +284,13 @@ outer:
return true
}
func mapReduce[Ea, Va Value, Vb any](
root *OpenEdge[Ea, Va],
mapVal func(Va) (Vb, error),
reduceEdge func(*OpenEdge[Ea, Va], []Vb) (Vb, error),
) (
Vb, error,
){
) {
if valA, ok := root.FromValue(); ok {
@ -361,7 +360,7 @@ func MapReduce[Ea, Va Value, Vb any](
reduceEdge func(Ea, []Vb) (Vb, error),
) (
Vb, error,
){
) {
var (
zeroB Vb

View File

@ -1,8 +1,8 @@
package graph
import (
"fmt"
"errors"
"fmt"
"strconv"
"testing"
@ -180,7 +180,7 @@ func TestMapReduce(t *testing.T) {
return TupleOut[Ea, Va](edge, ins...)
}
add := func() *mapReduceTestEdge{
add := func() *mapReduceTestEdge {
return &mapReduceTestEdge{
name: "add",
fn: func(ii []int) int {
@ -193,7 +193,7 @@ func TestMapReduce(t *testing.T) {
}
}
mul := func() *mapReduceTestEdge{
mul := func() *mapReduceTestEdge {
return &mapReduceTestEdge{
name: "mul",
fn: func(ii []int) int {

View File

@ -44,7 +44,6 @@ func evalThunks(args []Thunk) Thunk {
}
}
// Operation is an entity which can accept one or more arguments (each not
// having been evaluated yet) and return a Thunk which will perform some
// internal processing on those arguments and return a resultant Value.

View File

@ -74,5 +74,4 @@ var GlobalScope = ScopeMap{
"recur": Value{Operation: OperationFunc(func(args []Thunk, op Operation) (Thunk, error) {
return op.Perform(args, op)
})},
}

View File

@ -2,8 +2,8 @@
package vm
import (
"io"
"fmt"
"io"
"strings"
"github.com/mediocregopher/ginger/gg"