Skip to content

Commit

Permalink
new -compact mode, also use for eval when printing function objects (#84
Browse files Browse the repository at this point in the history
)

* new -compact mode, also use for eval when printing function objects

* use formatting vs running when -format is passed

* use the new ps.ComaList in object too

* compact form tests
  • Loading branch information
ldemailly authored Aug 1, 2024
1 parent e012b22 commit 38a3f9d
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 45 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,16 @@ See [Open Issues](https://grol.io/grol/issues) for what's left to do
### CLI Usage

```
grol 0.25.0 usage:
grol 0.29.0 usage:
grol [flags] *.gr files to interpret or `-` for stdin without prompt
or no arguments for stdin repl...
or 1 of the special arguments
grol {help|envhelp|version|buildinfo}
flags:
-c string
command/inline script to run instead of interactive mode
-compact
When printing code, use no indentation and most compact form
-eval
show eval results (default true)
-format
Expand Down
120 changes: 92 additions & 28 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type PrintState struct {
IndentLevel int
ExpressionLevel int
IndentationDone bool // already put N number of tabs, reset on each new line
Compact bool // don't indent at all (compact mode), no newlines, fewer spaces, no comments
prev Node
last string
}

func DebugString(n Node) string {
Expand All @@ -37,7 +40,9 @@ func (ps *PrintState) String() string {
// Only a single indentation per line.
func (ps *PrintState) Println(str ...string) *PrintState {
ps.Print(str...)
_, _ = ps.Out.Write([]byte{'\n'})
if !ps.Compact {
_, _ = ps.Out.Write([]byte{'\n'})
}
ps.IndentationDone = false
return ps
}
Expand All @@ -46,12 +51,13 @@ func (ps *PrintState) Print(str ...string) *PrintState {
if len(str) == 0 {
return ps // So for instance Println() doesn't print \t\n.
}
if !ps.IndentationDone && ps.IndentLevel > 1 {
if !ps.Compact && !ps.IndentationDone && ps.IndentLevel > 1 {
_, _ = ps.Out.Write([]byte(strings.Repeat("\t", ps.IndentLevel-1)))
ps.IndentationDone = true
}
for _, s := range str {
_, _ = ps.Out.Write([]byte(s))
ps.last = s
}
return ps
}
Expand Down Expand Up @@ -116,29 +122,59 @@ func needNewLineAfter(node Node) bool {
}
}

func isComment(node Node) bool {
_, ok := node.(*Comment)
return ok
}

// Compact mode: Skip comments and decide if we need a space separator or not.
func prettyPrintCompact(ps *PrintState, s Node, i int) bool {
if isComment(s) {
return true
}
_, prevIsExpr := ps.prev.(*InfixExpression)
// _, curIsID := s.(*Identifier)
if prevIsExpr && ps.last != "}" && ps.last != "]" {
if i > 0 {
_, _ = ps.Out.Write([]byte{' '})
}
}
return false
}

// Normal/long form print: Decide if using new line or space as separator.
func prettyPrintLongForm(ps *PrintState, s Node, i int) {
if i > 0 || ps.IndentLevel > 1 {
if keepSameLineAsPrevious(s) || !needNewLineAfter(ps.prev) {
log.Debugf("=> PrettyPrint adding just a space")
_, _ = ps.Out.Write([]byte{' '})
ps.IndentationDone = true
} else {
log.Debugf("=> PrettyPrint adding newline")
ps.Println()
}
}
}

func (p Statements) PrettyPrint(ps *PrintState) *PrintState {
oldExpressionLevel := ps.ExpressionLevel
if ps.IndentLevel > 0 {
ps.Print("{") // first statement might be a comment on same line.
}
ps.IndentLevel++
ps.ExpressionLevel = 0
var prev Node
for i, s := range p.Statements {
log.Debugf("PrettyPrint statement %T %s i %d\tcurSameLine=%v,\tcurHadNewline=%v,\tprevHadNewline=%v",
s, s.Value().Literal(), i, keepSameLineAsPrevious(s), needNewLineAfter(s), needNewLineAfter(prev))
if i > 0 || ps.IndentLevel > 1 {
if keepSameLineAsPrevious(s) || !needNewLineAfter(prev) {
log.Debugf("=> PrettyPrint adding just a space")
_, _ = ps.Out.Write([]byte{' '})
ps.IndentationDone = true
} else {
log.Debugf("=> PrettyPrint adding newline")
ps.Println()
var i int
for _, s := range p.Statements {
if ps.Compact {
if prettyPrintCompact(ps, s, i) {
continue // skip comments entirely.
}
} else {
prettyPrintLongForm(ps, s, i)
}
s.PrettyPrint(ps)
prev = s
ps.prev = s
i++
}
ps.Println()
ps.IndentLevel--
Expand Down Expand Up @@ -240,7 +276,11 @@ func (i InfixExpression) PrettyPrint(out *PrintState) *PrintState {
out.ExpressionLevel++
}
i.Left.PrettyPrint(out)
out.Print(" ", i.Literal(), " ")
if out.Compact {
out.Print(i.Literal())
} else {
out.Print(" ", i.Literal(), " ")
}
i.Right.PrettyPrint(out)
if !isAssign {
out.ExpressionLevel--
Expand All @@ -266,11 +306,17 @@ type IfExpression struct {
func (ie IfExpression) PrettyPrint(out *PrintState) *PrintState {
out.Print("if ")
ie.Condition.PrettyPrint(out)
out.Print(" ")
if !out.Compact {
out.Print(" ")
}
ie.Consequence.PrettyPrint(out)

if ie.Alternative != nil {
out.Print(" else ")
if out.Compact {
out.Print("else")
} else {
out.Print(" else ")
}
ie.Alternative.PrettyPrint(out)
}
return out
Expand All @@ -294,7 +340,7 @@ type Builtin struct {
func (b Builtin) PrettyPrint(out *PrintState) *PrintState {
out.Print(b.Literal())
out.Print("(")
PrintList(out, b.Parameters, ", ")
out.ComaList(b.Parameters)
out.Print(")")
return out
}
Expand All @@ -308,8 +354,12 @@ type FunctionLiteral struct {
func (fl FunctionLiteral) PrettyPrint(out *PrintState) *PrintState {
out.Print(fl.Literal())
out.Print("(")
PrintList(out, fl.Parameters, ", ")
out.Print(") ")
out.ComaList(fl.Parameters)
if out.Compact {
out.Print(")")
} else {
out.Print(") ")
}
fl.Body.PrettyPrint(out)
return out
}
Expand All @@ -325,7 +375,7 @@ func (ce CallExpression) PrettyPrint(out *PrintState) *PrintState {
out.Print("(")
oldExpressionLevel := out.ExpressionLevel
out.ExpressionLevel = 0
PrintList(out, ce.Arguments, ", ")
out.ComaList(ce.Arguments)
out.ExpressionLevel = oldExpressionLevel
out.Print(")")
return out
Expand All @@ -338,9 +388,8 @@ type ArrayLiteral struct {

func (al ArrayLiteral) PrettyPrint(out *PrintState) *PrintState {
out.Print("[")
PrintList(out, al.Elements, ", ")
out.ComaList(al.Elements)
out.Print("]")

return out
}

Expand All @@ -356,7 +405,6 @@ func (ie IndexExpression) PrettyPrint(out *PrintState) *PrintState {
out.Print("[")
ie.Index.PrettyPrint(out)
out.Print("])")

return out
}

Expand All @@ -368,9 +416,13 @@ type MapLiteral struct {

func (hl MapLiteral) PrettyPrint(out *PrintState) *PrintState {
out.Print("{")
sep := ", "
if out.Compact {
sep = ","
}
for i, key := range hl.Order {
if i > 0 {
out.Print(", ")
out.Print(sep)
}
key.PrettyPrint(out)
out.Print(":")
Expand All @@ -389,8 +441,20 @@ type MacroLiteral struct {
func (ml MacroLiteral) PrettyPrint(out *PrintState) *PrintState {
out.Print(ml.Literal())
out.Print("(")
PrintList(out, ml.Parameters, ", ")
out.Print(") ")
out.ComaList(ml.Parameters)
if out.Compact {
out.Print(")")
} else {
out.Print(") ")
}
ml.Body.PrettyPrint(out)
return out
}

func (ps *PrintState) ComaList(list []Node) {
sep := ", "
if ps.Compact {
sep = ","
}
PrintList(ps, list, sep)
}
5 changes: 5 additions & 0 deletions check_samples_double_format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@ for file in "$@"; do
./grol $file > /tmp/output1
./grol /tmp/format2 > /tmp/output2
diff -u /tmp/output1 /tmp/output2
./grol -format -compact $file > /tmp/format3
./grol -format -compact /tmp/format3 > /tmp/format4
diff -u /tmp/format3 /tmp/format4
./grol /tmp/format4 > /tmp/output3
diff -u /tmp/output1 /tmp/output3
echo "---done---"
done
14 changes: 12 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func Main() int {
commandFlag := flag.String("c", "", "command/inline script to run instead of interactive mode")
showParse := flag.Bool("parse", false, "show parse tree")
format := flag.Bool("format", false, "don't execute, just parse and re format the input")
compact := flag.Bool("compact", false, "When printing code, use no indentation and most compact form")
showEval := flag.Bool("eval", true, "show eval results")
sharedState := flag.Bool("shared-state", false, "All files share same interpreter state (default is new state for each)")
cli.ArgsHelp = "*.gr files to interpret or `-` for stdin without prompt or no arguments for stdin repl..."
Expand All @@ -30,6 +31,7 @@ func Main() int {
ShowParse: *showParse,
ShowEval: *showEval,
FormatOnly: *format,
Compact: *compact,
}
nArgs := len(flag.Args())
if *commandFlag != "" {
Expand Down Expand Up @@ -60,15 +62,23 @@ func Main() int {

func processOneFile(file string, s, macroState *eval.State, options repl.Options) {
if file == "-" {
log.Infof("Running on stdin")
if options.FormatOnly {
log.Infof("Formatting stdin")
} else {
log.Infof("Running on stdin")
}
repl.EvalAll(s, macroState, os.Stdin, os.Stdout, options)
return
}
f, err := os.Open(file)
if err != nil {
log.Fatalf("%v", err)
}
log.Infof("Running %s", file)
verb := "Running"
if options.FormatOnly {
verb = "Formatting"
}
log.Infof("%s %s", verb, file)
repl.EvalAll(s, macroState, f, os.Stdout, options)
f.Close()
}
2 changes: 1 addition & 1 deletion main_test.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ first(m["key"]) // get the value from key from map, which is an array, and the f

-- sample_test_stdout.gr --
macro test: greater
m is: {73:29, "key":[120, "abc", 73]} .
m is: {73:29,"key":[120,"abc",73]} .
Outputting a smiley: 😀
120
21 changes: 12 additions & 9 deletions object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,11 @@ func (f Function) Inspect() string {

out.WriteString("func")
out.WriteString("(")
ast.PrintList(&ast.PrintState{Out: &out}, f.Parameters, ", ")
out.WriteString(") ")
f.Body.PrettyPrint(&ast.PrintState{Out: &out})
ps := &ast.PrintState{Out: &out, Compact: true}
ps.ComaList(f.Parameters)
out.WriteString("){")
f.Body.PrettyPrint(ps)
out.WriteString("}")
return out.String()
}

Expand All @@ -204,7 +206,7 @@ type Array struct {
func (ao Array) Type() Type { return ARRAY }
func (ao Array) Inspect() string {
out := strings.Builder{}
WriteStrings(&out, ao.Elements, "[", ", ", "]")
WriteStrings(&out, ao.Elements, "[", ",", "]")
return out.String()
}

Expand Down Expand Up @@ -269,7 +271,7 @@ func (m Map) Inspect() string {
sort.Sort(keys)
for i, k := range keys {
if i != 0 {
out.WriteString(", ")
out.WriteString(",")
}
v := m[k]
out.WriteString(k.Inspect())
Expand Down Expand Up @@ -303,9 +305,10 @@ func (m Macro) Type() Type { return MACRO }
func (m Macro) Inspect() string {
out := strings.Builder{}
out.WriteString("macro(")
ast.PrintList(&ast.PrintState{Out: &out}, m.Parameters, ", ")
out.WriteString(") {\n")
m.Body.PrettyPrint(&ast.PrintState{Out: &out})
out.WriteString("\n}")
ps := &ast.PrintState{Out: &out, Compact: true}
ps.ComaList(m.Parameters)
out.WriteString("){")
m.Body.PrettyPrint(ps)
out.WriteString("}")
return out.String()
}
Loading

0 comments on commit 38a3f9d

Please sign in to comment.