aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--expr.go9
-rw-r--r--expr_test.go6
-rw-r--r--func.go44
3 files changed, 55 insertions, 4 deletions
diff --git a/expr.go b/expr.go
index 8d1ad82..910a2fc 100644
--- a/expr.go
+++ b/expr.go
@@ -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 {
diff --git a/func.go b/func.go
index 7d7af5a..fc9350c 100644
--- a/func.go
+++ b/func.go
@@ -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 }