aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-09-09 14:51:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-09-09 14:51:48 +0200
commit8a9870ed59225972de389b7b4a494a57390bff1b (patch)
tree280788395cb1895bb2367c931b94c6fe711426ea
parent7a2f5753a12a68e87f8556f6e833710f147533b2 (diff)
Add initial support for function calls: $func(a b c)
Now it is just a stub that prints the function name and its argument. Currently only single argument can be passed (no value pack support yet).
-rw-r--r--build/parser.cxx86
-rw-r--r--tests/eval/buildfile1
-rw-r--r--tests/function/call/buildfile15
-rw-r--r--tests/function/call/test.out7
-rwxr-xr-xtests/function/call/test.sh3
5 files changed, 85 insertions, 27 deletions
diff --git a/build/parser.cxx b/build/parser.cxx
index d68bcd9..42b9a98 100644
--- a/build/parser.cxx
+++ b/build/parser.cxx
@@ -401,6 +401,14 @@ namespace build
continue;
}
+ // Allow things like function calls that don't result in anything.
+ //
+ if (tt == type::newline && ns.empty ())
+ {
+ next (t, tt);
+ continue;
+ }
+
fail (t) << "unexpected " << t;
}
}
@@ -1034,7 +1042,7 @@ namespace build
// pretty quickly end up with a list of names that we need
// to splice into the result.
//
- names_type lv_eval;
+ names_type lv_data;
const names_type* plv;
location loc;
@@ -1063,58 +1071,82 @@ namespace build
// Make sure the result of evaluation is a single, simple name.
//
if (ns.size () != 1 || !ns.front ().simple ())
- fail (loc) << "variable name expected instead of '" << ns << "'";
+ fail (loc) << "variable/function name expected instead of '"
+ << ns << "'";
n = move (ns.front ().value);
}
else
- fail (t) << "variable name expected instead of " << t;
+ fail (t) << "variable/function name expected instead of " << t;
if (n.empty ())
- fail (loc) << "empty variable name";
+ fail (loc) << "empty variable/function name";
- // Process variable name.
+ // Figure out whether this is a variable expansion of a function
+ // call.
//
- if (n.front () == '.') // Fully qualified name.
- n.erase (0, 1);
- else
+ tt = peek ();
+
+ if (tt == type::lparen)
{
- //@@ TODO: append namespace if any.
- }
+ next (t, tt); // Get '('.
+ names_type ns (eval (t, tt));
- // Lookup.
- //
- const auto& var (variable_pool.find (move (n)));
- auto l (target_ != nullptr ? (*target_)[var] : (*scope_)[var]);
+ // Just a stub for now.
+ //
+ cout << n << "(" << ns << ")" << endl;
- // Undefined/NULL namespace variables are not allowed.
- //
- if (!l && var.name.find ('.') != string::npos)
- fail (loc) << "undefined/null namespace variable " << var.name;
+ tt = peek ();
- tt = peek ();
+ if (lv_data.empty ())
+ continue;
- if (!l || l->empty ())
- continue;
+ plv = &lv_data;
+ what = "function call";
+ }
+ else
+ {
+ // Process variable name.
+ //
+ if (n.front () == '.') // Fully qualified name.
+ n.erase (0, 1);
+ else
+ {
+ //@@ TODO: append namespace if any.
+ }
+
+ // Lookup.
+ //
+ const auto& var (variable_pool.find (move (n)));
+ auto l (target_ != nullptr ? (*target_)[var] : (*scope_)[var]);
- plv = &l->data_;
- what = "variable expansion";
+ // Undefined/NULL namespace variables are not allowed.
+ //
+ if (!l && var.name.find ('.') != string::npos)
+ fail (loc) << "undefined/null namespace variable " << var.name;
+
+ if (!l || l->empty ())
+ continue;
+
+ plv = &l->data_;
+ what = "variable expansion";
+ }
}
else
{
loc = get_location (t, &path_);
- lv_eval = eval (t, tt);
+ lv_data = eval (t, tt);
tt = peek ();
- if (lv_eval.empty ())
+ if (lv_data.empty ())
continue;
- plv = &lv_eval;
+ plv = &lv_data;
what = "context evaluation";
}
- // @@ Could move if (lv == &lv_eval).
+ // @@ Could move if (lv == &lv_data).
//
const names_type& lv (*plv);
diff --git a/tests/eval/buildfile b/tests/eval/buildfile
index c658d3b..cf315b6 100644
--- a/tests/eval/buildfile
+++ b/tests/eval/buildfile
@@ -1,4 +1,5 @@
(./):
+()
# Invalid.
#
diff --git a/tests/function/call/buildfile b/tests/function/call/buildfile
new file mode 100644
index 0000000..93eba14
--- /dev/null
+++ b/tests/function/call/buildfile
@@ -0,0 +1,15 @@
+$identity()
+$identity (a)
+$identity (a b c)
+$identity(sub/dir{x y z})
+
+# Verify we can inhibit function call with quoting.
+#
+foo = FOO
+bar = BAR
+
+print $foo"($bar)"
+print "$foo"($bar)
+print "$foo""($bar)"
+
+./:
diff --git a/tests/function/call/test.out b/tests/function/call/test.out
new file mode 100644
index 0000000..abc5974
--- /dev/null
+++ b/tests/function/call/test.out
@@ -0,0 +1,7 @@
+identity()
+identity(a)
+identity(a b c)
+identity(sub/dir{x} sub/dir{y} sub/dir{z})
+FOOBAR
+FOOBAR
+FOOBAR
diff --git a/tests/function/call/test.sh b/tests/function/call/test.sh
new file mode 100755
index 0000000..b898b3c
--- /dev/null
+++ b/tests/function/call/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+valgrind -q b -q | diff -u test.out -