diff options
-rw-r--r-- | expr.go | 9 | ||||
-rw-r--r-- | expr_test.go | 6 | ||||
-rw-r--r-- | func.go | 44 |
3 files changed, 55 insertions, 4 deletions
@@ -390,7 +390,7 @@ func parseFunc(f Func, in []byte, s int, term []byte, funcName string) (Value, i return nil, 0, err } v = concatLine(v) - // TODO(ukai): do this in funcIf, funcAnd, or funcOr? + // TODO(ukai): do this in funcIf, funcAnd, or funcOr's compactor? if (narg == 1 && funcName == "if") || funcName == "and" || funcName == "or" { v = trimLiteralSpace(v) } @@ -406,12 +406,19 @@ func parseFunc(f Func, in []byte, s int, term []byte, funcName string) (Value, i break } } + if compactor, ok := f.(Compactor); ok { + f = compactor.Compact() + } if katiStatsFlag { f = funcstats{f} } return f, i, nil } +type Compactor interface { + Compact() Func +} + type funcstats struct { Func } diff --git a/expr_test.go b/expr_test.go index 83b9b26..e21d66c 100644 --- a/expr_test.go +++ b/expr_test.go @@ -204,6 +204,12 @@ func TestParseExpr(t *testing.T) { }, }, }, + { + in: `$(eval ## comment)`, + val: &funcNop{ + expr: `$(eval ## comment)`, + }, + }, } { val, _, err := parseExpr([]byte(tc.in), nil) if tc.isErr { @@ -612,9 +612,6 @@ func (f *funcEval) Arity() int { return 1 } func (f *funcEval) Eval(w io.Writer, ev *Evaluator) { assertArity("eval", 1, len(f.args)) s := ev.Value(f.args[1]) - if len(s) == 0 || (s[0] == '#' && bytes.IndexByte(s, '\n') < 0) { - return - } mk, err := ParseMakefileBytes(s, ev.filename, ev.lineno) if err != nil { panic(err) @@ -625,6 +622,47 @@ func (f *funcEval) Eval(w io.Writer, ev *Evaluator) { } } +func (f *funcEval) Compact() Func { + if len(f.args)-1 < 1 { + return f + } + switch f.args[1].(type) { + case literal, tmpval: + default: + // TODO(ukai): eval -> varassign. e.g. $(eval foo := $(x)) + return f + } + arg := f.args[1].String() + arg = stripComment(arg) + if arg == "" { + return &funcNop{expr: f.String()} + } + // TODO(ukai): preserve comment for String()? + f.args[1] = literal(arg) + return f +} + +func stripComment(arg string) string { + for { + i := strings.Index(arg, "#") + if i < 0 { + return arg + } + eol := strings.Index(arg[i:], "\n") + if eol < 0 { + return arg[:i] + } + arg = arg[:i] + arg[eol+1:] + } +} + +type funcNop struct{ expr string } + +func (f *funcNop) Arity() int { return 0 } +func (f *funcNop) AddArg(Value) {} +func (f *funcNop) String() string { return f.expr } +func (f *funcNop) Eval(io.Writer, *Evaluator) {} + // http://www.gnu.org/software/make/manual/make.html#Origin-Function type funcOrigin struct{ fclosure } |