WIP: clean up locatable stuff
This commit is contained in:
parent
b2f67afe50
commit
303d40a6c3
@ -25,10 +25,6 @@ func (e LocatedError) Error() string {
|
|||||||
return fmt.Sprintf("%d:%d: %v", e.Row, e.Col, e.Err)
|
return fmt.Sprintf("%d:%d: %v", e.Row, e.Col, e.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type locatable interface {
|
|
||||||
locate() Location
|
|
||||||
}
|
|
||||||
|
|
||||||
type locatableRune struct {
|
type locatableRune struct {
|
||||||
Location
|
Location
|
||||||
r rune
|
r rune
|
||||||
@ -38,12 +34,3 @@ type locatableString struct {
|
|||||||
Location
|
Location
|
||||||
str string
|
str string
|
||||||
}
|
}
|
||||||
|
|
||||||
type locatableSlice[T locatable] []T
|
|
||||||
|
|
||||||
func (s locatableSlice[T]) locate() Location {
|
|
||||||
if len(s) == 0 {
|
|
||||||
panic("can't locate empty locatableSlice")
|
|
||||||
}
|
|
||||||
return s[0].locate()
|
|
||||||
}
|
|
||||||
|
104
gg/v2/term.go
104
gg/v2/term.go
@ -28,11 +28,7 @@ func (str stringerStr) String() string {
|
|||||||
return string(str)
|
return string(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO in the end I don't think locatable is actually needed here... I think
|
type term[T any] struct {
|
||||||
// seq is the only place where locating anything is required generally, and
|
|
||||||
// that's done using Decoder.nextLoc. Otherwise the Location is used when
|
|
||||||
// constructing Value's, which only really requires runes to be locatable.
|
|
||||||
type term[T locatable] struct {
|
|
||||||
name fmt.Stringer
|
name fmt.Stringer
|
||||||
decodeFn func(d *Decoder) (T, error)
|
decodeFn func(d *Decoder) (T, error)
|
||||||
}
|
}
|
||||||
@ -41,7 +37,7 @@ func (t term[T]) String() string {
|
|||||||
return t.name.String()
|
return t.name.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func firstOf[T locatable](terms ...*term[T]) *term[T] {
|
func firstOf[T any](terms ...*term[T]) *term[T] {
|
||||||
if len(terms) < 2 {
|
if len(terms) < 2 {
|
||||||
panic("firstOfTerms requires at least 2 terms")
|
panic("firstOfTerms requires at least 2 terms")
|
||||||
}
|
}
|
||||||
@ -72,11 +68,11 @@ func firstOf[T locatable](terms ...*term[T]) *term[T] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func seq[Ta, Tb, Tc locatable](
|
func seq[Ta, Tb, Tc any](
|
||||||
name fmt.Stringer,
|
name fmt.Stringer,
|
||||||
termA *term[Ta],
|
termA *term[Ta],
|
||||||
termB *term[Tb],
|
termB *term[Tb],
|
||||||
fn func(Ta, Tb) (Tc, error), // TODO probably don't need error return
|
fn func(Ta, Tb) Tc,
|
||||||
) *term[Tc] {
|
) *term[Tc] {
|
||||||
return &term[Tc]{
|
return &term[Tc]{
|
||||||
name: name,
|
name: name,
|
||||||
@ -95,30 +91,25 @@ func seq[Ta, Tb, Tc locatable](
|
|||||||
return zero, err
|
return zero, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vc, err := fn(va, vb)
|
return fn(va, vb), nil
|
||||||
if err != nil {
|
|
||||||
return zero, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return vc, nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchAndSkip[Ta, Tb locatable](
|
func matchAndSkip[Ta, Tb any](
|
||||||
termA *term[Ta], termB *term[Tb],
|
termA *term[Ta], termB *term[Tb],
|
||||||
) *term[Tb] {
|
) *term[Tb] {
|
||||||
return seq(termA, termA, termB, func(_ Ta, b Tb) (Tb, error) {
|
return seq(termA, termA, termB, func(_ Ta, b Tb) Tb {
|
||||||
return b, nil
|
return b
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func oneOrMore[T locatable](t *term[T]) *term[locatableSlice[T]] {
|
func oneOrMore[T any](t *term[T]) *term[[]T] {
|
||||||
return &term[locatableSlice[T]]{
|
return &term[[]T]{
|
||||||
name: stringerFn(func() string {
|
name: stringerFn(func() string {
|
||||||
return fmt.Sprintf("one or more %v", t)
|
return fmt.Sprintf("one or more %v", t)
|
||||||
}),
|
}),
|
||||||
decodeFn: func(d *Decoder) (locatableSlice[T], error) {
|
decodeFn: func(d *Decoder) ([]T, error) {
|
||||||
var vv []T
|
var vv []T
|
||||||
for {
|
for {
|
||||||
v, err := t.decodeFn(d)
|
v, err := t.decodeFn(d)
|
||||||
@ -140,12 +131,12 @@ func oneOrMore[T locatable](t *term[T]) *term[locatableSlice[T]] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func zeroOrMore[T locatable](t *term[T]) *term[locatableSlice[T]] {
|
func zeroOrMore[T any](t *term[T]) *term[[]T] {
|
||||||
return &term[locatableSlice[T]]{
|
return &term[[]T]{
|
||||||
name: stringerFn(func() string {
|
name: stringerFn(func() string {
|
||||||
return fmt.Sprintf("zero or more %v", t)
|
return fmt.Sprintf("zero or more %v", t)
|
||||||
}),
|
}),
|
||||||
decodeFn: func(d *Decoder) (locatableSlice[T], error) {
|
decodeFn: func(d *Decoder) ([]T, error) {
|
||||||
var vv []T
|
var vv []T
|
||||||
for {
|
for {
|
||||||
v, err := t.decodeFn(d)
|
v, err := t.decodeFn(d)
|
||||||
@ -163,7 +154,7 @@ func zeroOrMore[T locatable](t *term[T]) *term[locatableSlice[T]] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapTerm[Ta locatable, Tb locatable](
|
func mapTerm[Ta, Tb any](
|
||||||
name fmt.Stringer, t *term[Ta], fn func(Ta) Tb,
|
name fmt.Stringer, t *term[Ta], fn func(Ta) Tb,
|
||||||
) *term[Tb] {
|
) *term[Tb] {
|
||||||
return &term[Tb]{
|
return &term[Tb]{
|
||||||
@ -209,7 +200,7 @@ func runeTerm(r rune) *term[locatableRune] {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func locatableRunesToString(rr locatableSlice[locatableRune]) string {
|
func locatableRunesToString(rr []locatableRune) string {
|
||||||
str := make([]rune, len(rr))
|
str := make([]rune, len(rr))
|
||||||
for i := range rr {
|
for i := range rr {
|
||||||
str[i] = rr[i].r
|
str[i] = rr[i].r
|
||||||
@ -218,11 +209,11 @@ func locatableRunesToString(rr locatableSlice[locatableRune]) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runesToStringTerm(
|
func runesToStringTerm(
|
||||||
t *term[locatableSlice[locatableRune]],
|
t *term[[]locatableRune],
|
||||||
) *term[locatableString] {
|
) *term[locatableString] {
|
||||||
return mapTerm(
|
return mapTerm(
|
||||||
t, t, func(rr locatableSlice[locatableRune]) locatableString {
|
t, t, func(rr []locatableRune) locatableString {
|
||||||
return locatableString{rr.locate(), locatableRunesToString(rr)}
|
return locatableString{rr[0].locate(), locatableRunesToString(rr)}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -239,10 +230,8 @@ var (
|
|||||||
stringerStr("negative-number"),
|
stringerStr("negative-number"),
|
||||||
runeTerm('-'),
|
runeTerm('-'),
|
||||||
positiveNumberTerm,
|
positiveNumberTerm,
|
||||||
func(neg locatableRune, posNum locatableString) (locatableString, error) {
|
func(neg locatableRune, posNum locatableString) locatableString {
|
||||||
return locatableString{
|
return locatableString{neg.locate(), string(neg.r) + posNum.str}
|
||||||
neg.locate(), string(neg.r) + posNum.str,
|
|
||||||
}, nil
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -274,9 +263,9 @@ var (
|
|||||||
stringerStr("name"),
|
stringerStr("name"),
|
||||||
letterTerm,
|
letterTerm,
|
||||||
letterTailTerm,
|
letterTailTerm,
|
||||||
func(head locatableRune, tail locatableSlice[locatableRune]) (Value, error) {
|
func(head locatableRune, tail []locatableRune) Value {
|
||||||
name := string(head.r) + locatableRunesToString(tail)
|
name := string(head.r) + locatableRunesToString(tail)
|
||||||
return Value{Name: &name, Location: head.locate()}, nil
|
return Value{Name: &name, Location: head.locate()}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -293,19 +282,12 @@ func openEdgeIntoValue(val Value, oe *OpenEdge) *OpenEdge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var graphTerm = func() *term[Value] {
|
var graphTerm = func() *term[Value] {
|
||||||
type locatableOpenEdge struct {
|
|
||||||
Location
|
|
||||||
oe *OpenEdge
|
|
||||||
}
|
|
||||||
|
|
||||||
type tupleState struct {
|
type tupleState struct {
|
||||||
Location // location of last place tupleState was updated
|
|
||||||
ins []*OpenEdge
|
ins []*OpenEdge
|
||||||
oe *OpenEdge
|
oe *OpenEdge
|
||||||
}
|
}
|
||||||
|
|
||||||
type graphState struct {
|
type graphState struct {
|
||||||
Location // location of last place graphState was updated
|
|
||||||
g *Graph
|
g *Graph
|
||||||
oe *OpenEdge
|
oe *OpenEdge
|
||||||
}
|
}
|
||||||
@ -318,7 +300,7 @@ var graphTerm = func() *term[Value] {
|
|||||||
func(lr locatableRune) tupleState {
|
func(lr locatableRune) tupleState {
|
||||||
// if ')', then map that to an empty state. This acts as a
|
// if ')', then map that to an empty state. This acts as a
|
||||||
// sentinel value to indicate "end of tuple".
|
// sentinel value to indicate "end of tuple".
|
||||||
return tupleState{Location: lr.locate()}
|
return tupleState{}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -329,7 +311,7 @@ var graphTerm = func() *term[Value] {
|
|||||||
func(lr locatableRune) graphState {
|
func(lr locatableRune) graphState {
|
||||||
// if '}', then map that to an empty state. This acts as a
|
// if '}', then map that to an empty state. This acts as a
|
||||||
// sentinel value to indicate "end of graph".
|
// sentinel value to indicate "end of graph".
|
||||||
return graphState{Location: lr.locate()}
|
return graphState{}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -339,7 +321,7 @@ var graphTerm = func() *term[Value] {
|
|||||||
// deal with recursive dependencies between them.
|
// deal with recursive dependencies between them.
|
||||||
valueTerm = new(term[Value])
|
valueTerm = new(term[Value])
|
||||||
|
|
||||||
tupleTerm = new(term[locatableOpenEdge])
|
tupleTerm = new(term[*OpenEdge])
|
||||||
tupleTailTerm = new(term[tupleState])
|
tupleTailTerm = new(term[tupleState])
|
||||||
tupleOpenEdgeTerm = new(term[tupleState])
|
tupleOpenEdgeTerm = new(term[tupleState])
|
||||||
tupleOpenEdgeTailTerm = new(term[tupleState])
|
tupleOpenEdgeTailTerm = new(term[tupleState])
|
||||||
@ -355,13 +337,9 @@ var graphTerm = func() *term[Value] {
|
|||||||
stringerStr("tuple"),
|
stringerStr("tuple"),
|
||||||
runeTerm('('),
|
runeTerm('('),
|
||||||
tupleTailTerm,
|
tupleTailTerm,
|
||||||
func(lr locatableRune, ts tupleState) (locatableOpenEdge, error) {
|
func(lr locatableRune, ts tupleState) *OpenEdge {
|
||||||
slices.Reverse(ts.ins)
|
slices.Reverse(ts.ins)
|
||||||
oe := graph.TupleOut(None, ts.ins...)
|
return graph.TupleOut(None, ts.ins...)
|
||||||
return locatableOpenEdge{
|
|
||||||
Location: lr.locate(),
|
|
||||||
oe: oe,
|
|
||||||
}, nil
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -382,10 +360,9 @@ var graphTerm = func() *term[Value] {
|
|||||||
valueTerm,
|
valueTerm,
|
||||||
valueTerm,
|
valueTerm,
|
||||||
tupleOpenEdgeTailTerm,
|
tupleOpenEdgeTailTerm,
|
||||||
func(val Value, ts tupleState) (tupleState, error) {
|
func(val Value, ts tupleState) tupleState {
|
||||||
ts.oe = openEdgeIntoValue(val, ts.oe)
|
ts.oe = openEdgeIntoValue(val, ts.oe)
|
||||||
ts.Location = val.locate()
|
return ts
|
||||||
return ts, nil
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -399,12 +376,12 @@ var graphTerm = func() *term[Value] {
|
|||||||
stringerStr("graph"),
|
stringerStr("graph"),
|
||||||
runeTerm('{'),
|
runeTerm('{'),
|
||||||
graphTailTerm,
|
graphTailTerm,
|
||||||
func(lr locatableRune, gs graphState) (Value, error) {
|
func(lr locatableRune, gs graphState) Value {
|
||||||
if gs.g == nil {
|
if gs.g == nil {
|
||||||
gs.g = new(Graph)
|
gs.g = new(Graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Value{Graph: gs.g, Location: lr.locate()}, nil
|
return Value{Graph: gs.g, Location: lr.locate()}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -414,15 +391,14 @@ var graphTerm = func() *term[Value] {
|
|||||||
nameTerm,
|
nameTerm,
|
||||||
nameTerm,
|
nameTerm,
|
||||||
matchAndSkip(runeTerm('='), graphOpenEdgeTerm),
|
matchAndSkip(runeTerm('='), graphOpenEdgeTerm),
|
||||||
func(name Value, gs graphState) (graphState, error) {
|
func(name Value, gs graphState) graphState {
|
||||||
if gs.g == nil {
|
if gs.g == nil {
|
||||||
gs.g = new(Graph)
|
gs.g = new(Graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
gs.g = gs.g.AddValueIn(name, gs.oe)
|
gs.g = gs.g.AddValueIn(name, gs.oe)
|
||||||
gs.oe = nil
|
gs.oe = nil
|
||||||
gs.Location = name.locate()
|
return gs
|
||||||
return gs, nil
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -432,20 +408,18 @@ var graphTerm = func() *term[Value] {
|
|||||||
valueTerm,
|
valueTerm,
|
||||||
valueTerm,
|
valueTerm,
|
||||||
graphOpenEdgeValueTailTerm,
|
graphOpenEdgeValueTailTerm,
|
||||||
func(val Value, gs graphState) (graphState, error) {
|
func(val Value, gs graphState) graphState {
|
||||||
gs.oe = openEdgeIntoValue(val, gs.oe)
|
gs.oe = openEdgeIntoValue(val, gs.oe)
|
||||||
gs.Location = val.locate()
|
return gs
|
||||||
return gs, nil
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
seq(
|
seq(
|
||||||
tupleTerm,
|
tupleTerm,
|
||||||
tupleTerm,
|
tupleTerm,
|
||||||
graphOpenEdgeTailTerm,
|
graphOpenEdgeTailTerm,
|
||||||
func(loe locatableOpenEdge, gs graphState) (graphState, error) {
|
func(oe *OpenEdge, gs graphState) graphState {
|
||||||
gs.oe = loe.oe
|
gs.oe = oe
|
||||||
gs.Location = loe.locate()
|
return gs
|
||||||
return gs, nil
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user