Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Make iterating over ListExpr easier.

Implement support for standard Python iteration, so it's no longer
necessary to access the 'items' member directly and one can iterate over
the expression (or get its length or convert it to a list…) instead.

This works even with some other expression types (NullExpr and IfExpr)
to make it easy to write code that doesn't have to worry about a
condition being used in some place where the author didn't expect it.
  • Loading branch information...
commit bd96b4419c70a7caf4c7f3bf463154bb32a99625 1 parent d830e00
@vslavik authored
View
28 src/bkl/expr.py
@@ -129,6 +129,12 @@ def as_py(self):
def __nonzero__(self):
return bool(self.items)
+ def __len__(self):
+ return len(self.items)
+
+ def __iter__(self):
+ return iter(self.items)
+
def __str__(self):
return "[%s]" % ", ".join(str(x) for x in self.items)
@@ -166,6 +172,12 @@ def as_py(self):
def __nonzero__(self):
return False
+ def __len__(self):
+ return 0
+
+ def __iter__(self):
+ return iter([])
+
def __str__(self):
return "null"
@@ -347,10 +359,7 @@ def __init__(self, cond, yes, no, pos=None):
self.value_no = no
def as_py(self):
- if self.cond.as_py():
- return self.value_yes.as_py()
- else:
- return self.value_no.as_py()
+ return self.get_value().as_py()
def get_value(self):
"""
@@ -363,13 +372,16 @@ def get_value(self):
def __nonzero__(self):
try:
- if self.cond.as_py():
- return bool(self.value_yes)
- else:
- return bool(self.value_no)
+ return bool(self.get_value())
except NonConstError:
return bool(self.value_yes) or bool(self.value_no)
+ def __len__(self):
+ return len(self.get_value())
+
+ def __iter__(self):
+ return iter(self.get_value())
+
def __str__(self):
return "(%s ? %s : %s)" % (self.cond, self.value_yes, self.value_no)
View
13 src/bkl/interpreter/simplify.py
@@ -63,15 +63,10 @@ def _process_children(self, children):
def list(self, e):
new, changed = self._process_children(e.items)
if changed:
- # FIXME: re-enable this later. This prevents simplification
- # of some of conditionally set lists, but is necessary as
- # long as toolsets code assumes properties have ListExpr
- # values and directly accesses ListExpr.items.
- # if len(new):
- # return ListExpr(new, pos=e.pos)
- # else:
- # return NullExpr(pos=e.pos)
- return ListExpr(new, pos=e.pos)
+ if len(new):
+ return ListExpr(new, pos=e.pos)
+ else:
+ return NullExpr(pos=e.pos)
else:
return e
View
8 src/bkl/makefile.py
@@ -199,8 +199,8 @@ def _get_submodule_deps(self, main, submodule):
inspect = [submodule] + [p for p in project.modules if p.is_submodule_of(submodule)]
for mod in inspect:
for target in mod.targets.itervalues():
- for dep in target["deps"].as_py():
- tdep = project.get_target(dep)
+ for dep in target["deps"]:
+ tdep = project.get_target(dep.as_py())
tmod = tdep.parent
if tmod.is_submodule_of(main):
while tmod.parent is not main:
@@ -279,8 +279,8 @@ def _format_dep(t):
out = node.outputs[0]
deps = [expr_fmt.format(i) for i in node.inputs]
- for dep in t["deps"].as_py():
- tdep = module.project.get_target(dep)
+ for dep in t["deps"]:
+ tdep = module.project.get_target(dep.as_py())
tdepstr = _format_dep(tdep)
deps.append(tdepstr)
if tdep.parent is not module:
View
4 src/bkl/plugins/action.py
@@ -67,6 +67,6 @@ class ActionTargetType(TargetType):
def get_build_subgraph(self, toolset, target):
# prefix each line with @ so that make doesn't output the commands:
- cmds = add_prefix("@", target["commands"]).items
- node = BuildNode(commands=cmds, name=target["id"])
+ cmds = add_prefix("@", target["commands"])
+ node = BuildNode(commands=list(cmds), name=target["id"])
return [node]
View
21 src/bkl/plugins/gnu.py
@@ -46,7 +46,7 @@ def _is_multiarch_target(target):
and be incompatible with gcc's -M* flags.
"""
try:
- return len(target["archs"].as_py()) > 1
+ return len(target["archs"]) > 1
except KeyError:
return False # not an executable
@@ -85,7 +85,8 @@ def is_supported(self, toolset):
def _arch_flags(self, toolset, target):
if isinstance(toolset, OSXGnuToolset):
flags = []
- for a in target["archs"].as_py():
+ for a in target["archs"]:
+ a = a.as_py()
if a in OSX_ARCH_FLAGS:
flags.append(LiteralExpr(OSX_ARCH_FLAGS[a]))
return flags
@@ -116,10 +117,10 @@ def commands(self, toolset, target, input, output):
cmd += [LiteralExpr(GCC_DEPS_FLAGS)]
# FIXME: evaluating the flags here every time is inefficient
cmd += self._arch_flags(toolset, target)
- cmd += bkl.expr.add_prefix("-D", target["defines"]).items
- cmd += bkl.expr.add_prefix("-I", target["includedirs"]).items
- cmd += target["compiler-options"].items
- cmd += target[self._options_prop_name].items
+ cmd += bkl.expr.add_prefix("-D", target["defines"])
+ cmd += bkl.expr.add_prefix("-I", target["includedirs"])
+ cmd += target["compiler-options"]
+ cmd += target[self._options_prop_name]
# FIXME: use a parser instead of constructing the expression manually
# in here
cmd.append(input)
@@ -129,10 +130,10 @@ def commands(self, toolset, target, input, output):
# add command for generating the deps:
cmd = [LiteralExpr("$(call cc_deps_cmd,%s,$(CPPFLAGS) $(%s)" %
(self._compiler, self._flags_var_name))]
- cmd += bkl.expr.add_prefix("-D", target["defines"]).items
- cmd += bkl.expr.add_prefix("-I", target["includedirs"]).items
- cmd += target["compiler-options"].items
- cmd += target[self._options_prop_name].items
+ cmd += bkl.expr.add_prefix("-D", target["defines"])
+ cmd += bkl.expr.add_prefix("-I", target["includedirs"])
+ cmd += target["compiler-options"]
+ cmd += target[self._options_prop_name]
cmd.append(input)
cmd.append(LiteralExpr(")"))
retval.append(ListExpr(cmd))
View
4 src/bkl/plugins/native.py
@@ -196,14 +196,14 @@ def _collect_all_libs(self, toolset, target, visited, deplibs, ldlibs):
return
visited.add(target)
project = target.project
- deps = [project.get_target(x) for x in target["deps"].as_py()]
+ deps = [project.get_target(x.as_py()) for x in target["deps"]]
todo = [x for x in deps if
isinstance(x.type, LibraryType) or isinstance(x.type, DllType)]
for dep in todo:
f = dep.type.target_file(toolset, dep)
if f not in deplibs:
deplibs.append(f)
- for lib in target["libs"].items:
+ for lib in target["libs"]:
# TODO: use some ordered-set type and just merge them
if lib not in ldlibs:
ldlibs.append(lib)
View
18 src/bkl/plugins/vs2010.py
@@ -592,7 +592,7 @@ def gen_for_target(self, target):
std_defs += ";_USRDLL;%s_EXPORTS" % target.name.upper()
std_defs += ";%(PreprocessorDefinitions)"
defs = bkl.expr.ListExpr(
- target["defines"].items +
+ list(target["defines"]) +
[bkl.expr.LiteralExpr(std_defs)])
n_cl.add("PreprocessorDefinitions", defs)
n_cl.add("MultiProcessorCompilation", True)
@@ -627,25 +627,25 @@ def gen_for_target(self, target):
n_link.add("EnableCOMDATFolding", True)
n_link.add("OptimizeReferences", True)
if not is_library:
- ldflags = target["link-options"].as_py()
+ ldflags = target["link-options"]
if ldflags:
- n_link.add("AdditionalOptions", "%s %%(AdditionalOptions)" % " ".join(ldflags))
+ n_link.add("AdditionalOptions", "%s %%(AdditionalOptions)" % " ".join(ldflags.as_py()))
if is_library:
- libs = target["libs"].as_py()
+ libs = target["libs"]
if libs:
n_lib = Node("Lib")
self._add_extra_options_to_node(target, n_lib)
n.add(n_lib)
- n_lib.add("AdditionalDependencies", " ".join("%s.lib" % x for x in libs))
- pre_build = target["pre-build-commands"].as_py()
+ n_lib.add("AdditionalDependencies", " ".join("%s.lib" % x.as_py() for x in libs))
+ pre_build = target["pre-build-commands"]
if pre_build:
n_script = Node("PreBuildEvent")
- n_script.add("Command", "\n".join(pre_build))
+ n_script.add("Command", "\n".join(pre_build.as_py()))
n.add(n_script)
- post_build = target["post-build-commands"].as_py()
+ post_build = target["post-build-commands"]
if post_build:
n_script = Node("PostBuildEvent")
- n_script.add("Command", "\n".join(post_build))
+ n_script.add("Command", "\n".join(post_build.as_py()))
n.add(n_script)
root.add(n)
View
18 tests/test_plumbing.py
@@ -33,6 +33,8 @@
import bkl.dumper
import bkl.io
+from bkl.expr import BoolValueExpr, ListExpr, LiteralExpr, ConcatExpr, NullExpr
+
import projects
projects_dir = os.path.dirname(projects.__file__)
@@ -65,7 +67,6 @@ def test_file_io_win(tmpdir):
def test_expr_as_bool():
- from bkl.expr import BoolValueExpr, ListExpr, LiteralExpr, ConcatExpr
bool_yes = BoolValueExpr(True)
bool_no = BoolValueExpr(False)
empty_list = ListExpr([])
@@ -83,3 +84,18 @@ def test_expr_as_bool():
assert not bool(empty_list)
assert not bool(empty_literal)
assert not bool(empty_concat)
+
+def test_list_expr_iterator():
+ bool_yes = BoolValueExpr(True)
+ bool_no = BoolValueExpr(False)
+ empty_list = ListExpr([])
+ a_list = ListExpr([bool_yes, bool_no])
+ assert len(empty_list) == 0
+ assert not empty_list
+ assert len(a_list) == 2
+ assert a_list
+ assert list(a_list) == [bool_yes, bool_no]
+
+ null = NullExpr()
+ assert not null
+ assert len(null) == 0
Please sign in to comment.
Something went wrong with that request. Please try again.