WIP: clean up locatable stuff

This commit is contained in:
Brian Picciano 2023-10-22 21:43:48 +02:00
parent b2f67afe50
commit 303d40a6c3
2 changed files with 43 additions and 82 deletions

View File

@ -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()
}

View File

@ -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
}, },
), ),
) )