Formatter option is now composed of two data: flags (lower 16 bits) and indentation size (higher 16 bits).
DictType and ListType formatter use both indent and flag options. Simple-store now makes a DictType from its data and its ToString() function returns dict.ToString()
This commit is contained in:
parent
56d6d06d15
commit
9fb611aa20
72
dict-type.go
72
dict-type.go
@ -32,42 +32,52 @@ func newDict(dictAny map[any]*term) (dict *DictType) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dict *DictType) toMultiLine(sb *strings.Builder, indent int) {
|
func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) {
|
||||||
sb.WriteString(strings.Repeat("\t", indent))
|
indent := GetFormatIndent(opt)
|
||||||
sb.WriteString("{\n")
|
flags := GetFormatFlags(opt)
|
||||||
|
//sb.WriteString(strings.Repeat(" ", indent))
|
||||||
|
sb.WriteByte('{')
|
||||||
|
|
||||||
first := true
|
if len(*dict) > 0 {
|
||||||
for name, value := range *dict {
|
innerOpt := MakeFormatOptions(flags, indent+1)
|
||||||
if first {
|
nest := strings.Repeat(" ", indent+1)
|
||||||
first = false
|
sb.WriteByte('\n')
|
||||||
} else {
|
|
||||||
sb.WriteByte(',')
|
|
||||||
sb.WriteByte('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.WriteString(strings.Repeat("\t", indent+1))
|
first := true
|
||||||
if key, ok := name.(string); ok {
|
for name, value := range *dict {
|
||||||
sb.WriteString(string('"') + key + string('"'))
|
if first {
|
||||||
} else {
|
first = false
|
||||||
sb.WriteString(fmt.Sprintf("%v", name))
|
} else {
|
||||||
}
|
sb.WriteByte(',')
|
||||||
sb.WriteString(": ")
|
sb.WriteByte('\n')
|
||||||
if f, ok := value.(Formatter); ok {
|
}
|
||||||
sb.WriteString(f.ToString(MultiLine))
|
|
||||||
} else if _, ok = value.(Functor); ok {
|
sb.WriteString(nest)
|
||||||
sb.WriteString("func(){}")
|
if key, ok := name.(string); ok {
|
||||||
} else {
|
sb.WriteString(string('"') + key + string('"'))
|
||||||
sb.WriteString(fmt.Sprintf("%v", value))
|
} else {
|
||||||
|
sb.WriteString(fmt.Sprintf("%v", name))
|
||||||
|
}
|
||||||
|
sb.WriteString(": ")
|
||||||
|
if f, ok := value.(Formatter); ok {
|
||||||
|
sb.WriteString(f.ToString(innerOpt))
|
||||||
|
} else if _, ok = value.(Functor); ok {
|
||||||
|
sb.WriteString("func(){}")
|
||||||
|
} else {
|
||||||
|
sb.WriteString(fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
sb.WriteByte('\n')
|
||||||
|
sb.WriteString(strings.Repeat(" ", indent))
|
||||||
}
|
}
|
||||||
sb.WriteString(strings.Repeat("\t", indent))
|
sb.WriteString("}")
|
||||||
sb.WriteString("\n}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dict *DictType) ToString(opt FmtOpt) string {
|
func (dict *DictType) ToString(opt FmtOpt) string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
if opt&MultiLine != 0 {
|
flags := GetFormatFlags(opt)
|
||||||
dict.toMultiLine(&sb, 0)
|
if flags&MultiLine != 0 {
|
||||||
|
dict.toMultiLine(&sb, opt)
|
||||||
} else {
|
} else {
|
||||||
sb.WriteByte('{')
|
sb.WriteByte('{')
|
||||||
first := true
|
first := true
|
||||||
@ -133,3 +143,9 @@ func (dict *DictType) setItem(key any, value any) (err error) {
|
|||||||
(*dict)[key] = value
|
(*dict)[key] = value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
type DictFormat interface {
|
||||||
|
ToDict() *DictType
|
||||||
|
}
|
||||||
|
14
formatter.go
14
formatter.go
@ -6,7 +6,7 @@ package expr
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type FmtOpt uint16
|
type FmtOpt uint32 // lower 16 bits hold a bit-mask, higher 16 bits hold an indentation number
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TTY FmtOpt = 1 << iota
|
TTY FmtOpt = 1 << iota
|
||||||
@ -30,6 +30,18 @@ func TruncateString(s string) (trunc string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeFormatOptions(flags FmtOpt, indent int) FmtOpt {
|
||||||
|
return FmtOpt(indent<<16) | flags
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFormatFlags(opt FmtOpt) FmtOpt {
|
||||||
|
return opt & 0xFFFF
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFormatIndent(opt FmtOpt) int {
|
||||||
|
return int(opt >> 16)
|
||||||
|
}
|
||||||
|
|
||||||
type Formatter interface {
|
type Formatter interface {
|
||||||
ToString(options FmtOpt) string
|
ToString(options FmtOpt) string
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ func (functor *baseFunctor) ToString(opt FmtOpt) (s string) {
|
|||||||
if functor.info != nil {
|
if functor.info != nil {
|
||||||
s = functor.info.ToString(opt)
|
s = functor.info.ToString(opt)
|
||||||
} else {
|
} else {
|
||||||
s = "func() {<body>}"
|
s = "func() {}"
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ func (info *funcInfo) ToString(opt FmtOpt) string {
|
|||||||
} else {
|
} else {
|
||||||
sb.WriteString(TypeAny)
|
sb.WriteString(TypeAny)
|
||||||
}
|
}
|
||||||
sb.WriteString(" {<body>}")
|
sb.WriteString(" {}")
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
list-type.go
23
list-type.go
@ -52,16 +52,24 @@ func ListFromStrings(stringList []string) (list *ListType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ls *ListType) ToString(opt FmtOpt) (s string) {
|
func (ls *ListType) ToString(opt FmtOpt) (s string) {
|
||||||
|
indent := GetFormatIndent(opt)
|
||||||
|
flags := GetFormatFlags(opt)
|
||||||
|
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
sb.WriteByte('[')
|
sb.WriteByte('[')
|
||||||
if len(*ls) > 0 {
|
if len(*ls) > 0 {
|
||||||
if opt&MultiLine != 0 {
|
innerOpt := MakeFormatOptions(flags, indent+1)
|
||||||
sb.WriteString("\n ")
|
nest := strings.Repeat(" ", indent+1)
|
||||||
|
|
||||||
|
if flags&MultiLine != 0 {
|
||||||
|
sb.WriteByte('\n')
|
||||||
|
sb.WriteString(nest)
|
||||||
}
|
}
|
||||||
for i, item := range []any(*ls) {
|
for i, item := range []any(*ls) {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
if opt&MultiLine != 0 {
|
if flags&MultiLine != 0 {
|
||||||
sb.WriteString(",\n ")
|
sb.WriteString(",\n")
|
||||||
|
sb.WriteString(nest)
|
||||||
} else {
|
} else {
|
||||||
sb.WriteString(", ")
|
sb.WriteString(", ")
|
||||||
}
|
}
|
||||||
@ -70,17 +78,20 @@ func (ls *ListType) ToString(opt FmtOpt) (s string) {
|
|||||||
sb.WriteByte('"')
|
sb.WriteByte('"')
|
||||||
sb.WriteString(s)
|
sb.WriteString(s)
|
||||||
sb.WriteByte('"')
|
sb.WriteByte('"')
|
||||||
|
} else if formatter, ok := item.(Formatter); ok {
|
||||||
|
sb.WriteString(formatter.ToString(innerOpt))
|
||||||
} else {
|
} else {
|
||||||
sb.WriteString(fmt.Sprintf("%v", item))
|
sb.WriteString(fmt.Sprintf("%v", item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if opt&MultiLine != 0 {
|
if flags&MultiLine != 0 {
|
||||||
sb.WriteByte('\n')
|
sb.WriteByte('\n')
|
||||||
|
sb.WriteString(strings.Repeat(" ", indent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.WriteByte(']')
|
sb.WriteByte(']')
|
||||||
s = sb.String()
|
s = sb.String()
|
||||||
if opt&Truncate != 0 && len(s) > TruncateSize {
|
if flags&Truncate != 0 && len(s) > TruncateSize {
|
||||||
s = TruncateString(s)
|
s = TruncateString(s)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -31,7 +31,9 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sourceCtx != nil {
|
if sourceCtx != nil {
|
||||||
if formatter, ok := sourceCtx.(Formatter); ok {
|
if formatter, ok := sourceCtx.(DictFormat); ok {
|
||||||
|
v = formatter.ToDict()
|
||||||
|
} else if formatter, ok := sourceCtx.(Formatter); ok {
|
||||||
v = formatter.ToString(0)
|
v = formatter.ToString(0)
|
||||||
} else {
|
} else {
|
||||||
// keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
|
// keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
|
||||||
|
@ -7,7 +7,7 @@ package expr
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
// "strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SimpleStore struct {
|
type SimpleStore struct {
|
||||||
@ -50,7 +50,7 @@ func (ctx *SimpleStore) Merge(src ExprContext) {
|
|||||||
ctx.funcStore[name], _ = src.GetFuncInfo(name)
|
ctx.funcStore[name], _ = src.GetFuncInfo(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) {
|
func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) {
|
||||||
sb.WriteString("vars: {\n")
|
sb.WriteString("vars: {\n")
|
||||||
first := true
|
first := true
|
||||||
@ -116,6 +116,49 @@ func (ctx *SimpleStore) ToString(opt FmtOpt) string {
|
|||||||
funcsCtxToBuilder(&sb, ctx, 0)
|
funcsCtxToBuilder(&sb, ctx, 0)
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (ctx *SimpleStore) ToString(opt FmtOpt) string {
|
||||||
|
dict := ctx.ToDict()
|
||||||
|
return dict.ToString(opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *SimpleStore) varsToDict(dict *DictType) *DictType {
|
||||||
|
names := ctx.EnumVars(nil)
|
||||||
|
slices.Sort(names)
|
||||||
|
for _, name := range ctx.EnumVars(nil) {
|
||||||
|
value, _ := ctx.GetVar(name)
|
||||||
|
if f, ok := value.(Formatter); ok {
|
||||||
|
(*dict)[name] = f.ToString(0)
|
||||||
|
} else if _, ok = value.(Functor); ok {
|
||||||
|
(*dict)[name] = "func(){}"
|
||||||
|
} else {
|
||||||
|
(*dict)[name] = fmt.Sprintf("%v", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *SimpleStore) funcsToDict(dict *DictType) *DictType {
|
||||||
|
names := ctx.EnumFuncs(func(name string) bool { return true })
|
||||||
|
slices.Sort(names)
|
||||||
|
for _, name := range names {
|
||||||
|
value, _ := ctx.GetFuncInfo(name)
|
||||||
|
if formatter, ok := value.(Formatter); ok {
|
||||||
|
(*dict)[name] = formatter.ToString(0)
|
||||||
|
} else {
|
||||||
|
(*dict)[name] = fmt.Sprintf("%v", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *SimpleStore) ToDict() (dict *DictType) {
|
||||||
|
dict = MakeDict()
|
||||||
|
(*dict)["variables"] = ctx.varsToDict(MakeDict())
|
||||||
|
(*dict)["functions"] = ctx.funcsToDict(MakeDict())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) {
|
func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) {
|
||||||
v, exists = ctx.varStore[varName]
|
v, exists = ctx.varStore[varName]
|
||||||
|
@ -110,7 +110,7 @@ func TestDictToStringMultiLine(t *testing.T) {
|
|||||||
var good bool
|
var good bool
|
||||||
section := "dict-ToString-ML"
|
section := "dict-ToString-ML"
|
||||||
want := `{
|
want := `{
|
||||||
"first": 1
|
"first": 1
|
||||||
}`
|
}`
|
||||||
args := map[any]*term{
|
args := map[any]*term{
|
||||||
"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)),
|
"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)),
|
||||||
|
@ -44,7 +44,7 @@ func dummy(ctx ExprContext, name string, args []any) (result any, err error) {
|
|||||||
|
|
||||||
func TestFunctionToStringSimple(t *testing.T) {
|
func TestFunctionToStringSimple(t *testing.T) {
|
||||||
source := NewGolangFunctor(dummy)
|
source := NewGolangFunctor(dummy)
|
||||||
want := "func() {<body>}"
|
want := "func() {}"
|
||||||
got := source.ToString(0)
|
got := source.ToString(0)
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf(`(func() -> result = %v [%T], want = %v [%T]`, got, got, want, want)
|
t.Errorf(`(func() -> result = %v [%T], want = %v [%T]`, got, got, want, want)
|
||||||
|
Loading…
Reference in New Issue
Block a user