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

@ -11,7 +11,7 @@ import (
// Type aliases for convenience
type (
Graph = graph.Graph[Value, Value]
Graph = graph.Graph[Value, Value]
OpenEdge = graph.OpenEdge[Value, Value]
)
@ -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

@ -52,7 +52,7 @@ func TestDecoder(t *testing.T) {
tOut(
n("a"),
vOut(n("b"),
i(1)),
i(1)),
),
),
},

View File

@ -113,7 +113,7 @@ func (oe OpenEdge[E, V]) FromTuple() ([]*OpenEdge[E, V], bool) {
// an edge (with edgeVal attached to it) coming from the vertex containing val.
func ValueOut[E, V Value](edgeVal E, val V) *OpenEdge[E, V] {
return &OpenEdge[E, V]{
val: &val,
val: &val,
edgeVal: edgeVal,
}
}
@ -127,7 +127,7 @@ func TupleOut[E, V Value](edgeVal E, ins ...*OpenEdge[E, V]) *OpenEdge[E, V] {
var (
zero V
in = ins[0]
in = ins[0]
)
if edgeVal.Equal(zero) {
@ -141,13 +141,13 @@ func TupleOut[E, V Value](edgeVal E, ins ...*OpenEdge[E, V]) *OpenEdge[E, V] {
}
return &OpenEdge[E, V]{
tup: ins,
tup: ins,
edgeVal: edgeVal,
}
}
type graphValueIn[E, V Value] struct {
val V
val V
edge *OpenEdge[E, V]
}
@ -163,13 +163,13 @@ func (valIn graphValueIn[E, V]) equal(valIn2 graphValueIn[E, V]) bool {
// lots of O(N) operations, unnecessary copying on changes, and duplicate data
// in memory.
type Graph[E, V Value] struct {
edges []*OpenEdge[E, V]
edges []*OpenEdge[E, V]
valIns []graphValueIn[E, V]
}
func (g *Graph[E, V]) cp() *Graph[E, V] {
cp := &Graph[E, V]{
edges: make([]*OpenEdge[E, V], len(g.edges)),
edges: make([]*OpenEdge[E, V], len(g.edges)),
valIns: make([]graphValueIn[E, V], len(g.valIns)),
}
copy(cp.edges, g.edges)
@ -243,7 +243,7 @@ func (g *Graph[E, V]) ValueIns(val Value) []*OpenEdge[E, V] {
func (g *Graph[E, V]) AddValueIn(val V, oe *OpenEdge[E, V]) *Graph[E, V] {
valIn := graphValueIn[E, V]{
val: val,
val: val,
edge: oe,
}
@ -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 {
@ -333,7 +332,7 @@ type mappedVal[Va Value, Vb any] struct {
type reducedEdge[Ea, Va Value, Vb any] struct {
edgeA *OpenEdge[Ea, Va]
valB Vb // result
valB Vb // result
}
// MapReduce recursively computes a resultant Value of type Vb from an
@ -361,7 +360,7 @@ func MapReduce[Ea, Va Value, Vb any](
reduceEdge func(Ea, []Vb) (Vb, error),
) (
Vb, error,
){
) {
var (
zeroB Vb
@ -370,7 +369,7 @@ func MapReduce[Ea, Va Value, Vb any](
// reduction is only performed a single time for each value/edge.
//
// NOTE this is not implemented very efficiently.
mappedVals []mappedVal[Va, Vb]
mappedVals []mappedVal[Va, Vb]
reducedEdges []reducedEdge[Ea, Va, Vb]
)
@ -413,7 +412,7 @@ func MapReduce[Ea, Va Value, Vb any](
reducedEdges = append(reducedEdges, reducedEdge[Ea, Va, Vb]{
edgeA: edgeA,
valB: valB,
valB: valB,
})
return valB, nil

View File

@ -1,8 +1,8 @@
package graph
import (
"fmt"
"errors"
"fmt"
"strconv"
"testing"
@ -129,7 +129,7 @@ func TestEqual(t *testing.T) {
type mapReduceTestEdge struct {
name string
fn func([]int) int
fn func([]int) int
done bool
}
@ -162,9 +162,9 @@ func (e *mapReduceTestEdge) do(ii []int) int {
func TestMapReduce(t *testing.T) {
type (
Va = I
Vb = int
Ea = *mapReduceTestEdge
Va = I
Vb = int
Ea = *mapReduceTestEdge
edge = OpenEdge[Ea, Va]
)
@ -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 {
@ -225,15 +225,15 @@ func TestMapReduce(t *testing.T) {
}
tests := []struct {
in *edge
in *edge
exp int
}{
{
in: vOut(nil, 1),
in: vOut(nil, 1),
exp: 10,
},
{
in: vOut(add(), 1),
in: vOut(add(), 1),
exp: 10,
},
{

View File

@ -30,7 +30,7 @@ func evalThunks(args []Thunk) Thunk {
return func() (Value, error) {
var (
err error
err error
tupVals = make([]Value, len(args))
)
@ -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

@ -115,9 +115,9 @@ func (m ScopeMap) NewScope() Scope {
type graphScope struct {
*gg.Graph
in Thunk
in Thunk
parent Scope
op Operation
op Operation
}
// ScopeFromGraph returns a Scope which will use the given Graph for evaluation.
@ -139,9 +139,9 @@ type graphScope struct {
func ScopeFromGraph(g *gg.Graph, in Thunk, parent Scope, op Operation) Scope {
return &graphScope{
Graph: g,
in: in,
in: in,
parent: parent,
op: op,
op: op,
}
}

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"