Repository: mesonbuild/meson

Issue:
Running "meson configure" in source directory raises an exception (again)
Sorry for the lack of an isolated test-case. Apparently [the Taisei repo](https://github.com/taisei-project/taisei/) can serve as a decent integration test for this feature in general.

Ping @mensinda 

```
[0] [akari@navi] [?master ← /home/akari/git/taisei]
 % meson configure
Unable to evaluate subdir([]) in AstInterpreter --> Skipping
Unable to evaluate subdir([]) in AstInterpreter --> Skipping
Traceback (most recent call last):
  File "/data/git/meson/mesonbuild/mesonmain.py", line 122, in run
    return options.run_func(options)
  File "/data/git/meson/mesonbuild/mconf.py", line 200, in run
    c = Conf(builddir)
  File "/data/git/meson/mesonbuild/mconf.py", line 56, in __init__
    intr.analyze()
  File "/data/git/meson/mesonbuild/ast/introspection.py", line 274, in analyze
    self.run()
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 407, in run
    self.evaluate_codeblock(self.ast, start=1)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 431, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 425, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 436, in evaluate_statement
    return self.function_call(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 773, in function_call
    return func(node, posargs, kwargs)
  File "/data/git/meson/mesonbuild/ast/interpreter.py", line 149, in func_subdir
    self.evaluate_codeblock(codeblock)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 431, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 425, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 446, in evaluate_statement
    return self.evaluate_if(cur)
  File "/data/git/meson/mesonbuild/ast/interpreter.py", line 216, in evaluate_if
    self.evaluate_codeblock(i.block)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 431, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 425, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 470, in evaluate_statement
    return self.evaluate_plusassign(cur)
  File "/data/git/meson/mesonbuild/ast/interpreter.py", line 177, in evaluate_plusassign
    self.assign_vals[node.var_name] += [self.evaluate_statement(node.value)]
KeyError: 'em_bundle_misc_packer_args'

[2] [akari@navi] [?master ← /home/akari/git/taisei]
 % git describe
v1.2-366-g387d16d6
```


Discussion:
I think the cause for this is access to the `em_bundle_misc_packer_args` variable, [which is declared dynamically via a call to `set_variable`, and never statically](https://github.com/taisei-project/taisei/blob/master/resources/meson.build). Assuming the introspection interpreter doesn't evaluate any function calls, this seems like a difficult problem. If there's no feasible solution, this limitation should be documented, and perhaps setting of undefined variables via `set_variable` should be deprecated.

Resolving patch:
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -171,6 +171,7 @@ def evaluate_plusassign(self, node):
         assert(isinstance(node, mparser.PlusAssignmentNode))
         if node.var_name not in self.assignments:
             self.assignments[node.var_name] = []
+            self.assign_vals[node.var_name] = []
         self.assignments[node.var_name] += [node.value] # Save a reference to the value node
         if hasattr(node.value, 'ast_id'):
             self.reverse_assignment[node.value.ast_id] = node


Test patch:
diff --git a/test cases/unit/55 introspection/meson.build b/test cases/unit/55 introspection/meson.build
--- a/test cases/unit/55 introspection/meson.build	
+++ b/test cases/unit/55 introspection/meson.build	
@@ -9,6 +9,9 @@ b2 = get_option('test_opt2')
 test_bool = b1 or b2
 test_bool = b1 and b2
 
+set_variable('list_test_plusassign', [])
+list_test_plusassign += ['bugs everywhere']
+
 if false
   dependency('somethingthatdoesnotexist', required: true)
   dependency('look_i_have_a_fallback', fallback: ['oh_no', 'the_subproject_does_not_exist'])