aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2013-02-10 00:50:46 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2013-02-10 00:50:46 +0200
commit45ecded01d814d0d0bf9b84c0dafa65575ab2bdd (patch)
treec65e38fb0455cc815ceddbe99f305fb8d0ebe7a8
parentda2e9f6688ea9545ccc056195ea36421e3e019aa (diff)
downloadmeson-45ecded01d814d0d0bf9b84c0dafa65575ab2bdd.zip
meson-45ecded01d814d0d0bf9b84c0dafa65575ab2bdd.tar.gz
meson-45ecded01d814d0d0bf9b84c0dafa65575ab2bdd.tar.bz2
Started work on keyword arguments.
-rwxr-xr-xbparser.py19
-rwxr-xr-xinterpreter.py43
-rw-r--r--nodes.py17
-rw-r--r--test cases/1 trivial/builder.txt6
4 files changed, 61 insertions, 24 deletions
diff --git a/bparser.py b/bparser.py
index 1611988..9d85597 100755
--- a/bparser.py
+++ b/bparser.py
@@ -42,6 +42,7 @@ tokens = ['LPAREN',
'INT',
'EOL_CONTINUE',
'EOL',
+ 'COLON',
] + list(reserved.values())
t_ASSIGN = '='
@@ -56,6 +57,7 @@ t_RBRACE = '\}'
t_COMMENT = '\#[^\n]*'
t_COMMA = ','
t_DOT = '\.'
+t_COLON = ':'
t_ignore = ' \t'
@@ -162,19 +164,32 @@ def p_statement_expression(t):
'statement : expression'
t[0] = nodes.statement_from_expression(t[1])
+
def p_args_multiple(t):
'args : statement COMMA args'
args = t[3]
args.prepend(t[1])
t[0] = args
-def p_args_single(t):
+def p_kwargs_multiple(t):
+ 'args : expression COLON statement COMMA args'
+ args = t[5]
+ args.add_kwarg(t[1], t[3])
+ t[0] = args
+
+def p_args_single_pos(t):
'args : statement'
args = nodes.Arguments(t.lineno(1))
args.prepend(t[1])
t[0] = args
-def p_args_none(t):
+def p_args_single_kw(t):
+ 'args : expression COLON statement'
+ a = nodes.Arguments(t.lineno(1))
+ a.set_kwarg(t[1], t[2])
+ t[0] = a
+
+def p_posargs_none(t):
'args :'
t[0] = nodes.Arguments(t.lineno(0))
diff --git a/interpreter.py b/interpreter.py
index 11c11f5..028154d 100755
--- a/interpreter.py
+++ b/interpreter.py
@@ -465,7 +465,7 @@ class Interpreter():
t = Test(args[0], args[1])
self.build.tests.append(t)
print('Adding test "%s"' % args[0])
-
+
def func_headers(self, node, args):
for a in args:
if not isinstance(a, str):
@@ -534,6 +534,8 @@ class Interpreter():
for a in args:
if isinstance(a, list):
result = result + self.flatten(a)
+ if isinstance(a, nodes.StringStatement):
+ result.append(a.get_value())
else:
result.append(a)
return result
@@ -559,9 +561,9 @@ class Interpreter():
def function_call(self, node):
func_name = node.get_function_name()
- args = self.reduce_arguments(node.arguments)
+ (posargs, kwargs) = self.reduce_arguments(node.arguments)
if func_name in self.funcs:
- return self.funcs[func_name](node, args)
+ return self.funcs[func_name](node, posargs)
else:
raise InvalidCode('Unknown function "%s".' % func_name)
@@ -587,24 +589,27 @@ class Interpreter():
raise InvalidCode('Line %d: Tried to assign an invalid value to variable.' % node.lineno())
self.set_variable(var_name, value)
return value
-
+
+ def reduce_single(self, arg):
+ if isinstance(arg, nodes.AtomExpression) or isinstance(arg, nodes.AtomStatement):
+ return self.get_variable(arg.value)
+ elif isinstance(arg, nodes.StringExpression) or isinstance(arg, nodes.StringStatement):
+ return arg.get_value()
+ elif isinstance(arg, nodes.FunctionCall):
+ return self.function_call(arg)
+ elif isinstance(arg, nodes.MethodCall):
+ return self.method_call(arg)
+ else:
+ raise InvalidCode('Line %d: Irreducible argument.' % args.lineno())
+
def reduce_arguments(self, args):
assert(isinstance(args, nodes.Arguments))
- reduced = []
- for arg in args.arguments:
- if isinstance(arg, nodes.AtomExpression) or isinstance(arg, nodes.AtomStatement):
- r = self.get_variable(arg.value)
- elif isinstance(arg, nodes.StringExpression) or isinstance(arg, nodes.StringStatement):
- r = arg.get_value()
- elif isinstance(arg, nodes.FunctionCall):
- r = self.function_call(arg)
- elif isinstance(arg, nodes.MethodCall):
- r = self.method_call(arg)
- else:
- raise InvalidCode('Line %d: Irreducible argument.' % args.lineno())
- reduced.append(r)
- assert(len(reduced) == len(args))
- return reduced
+ reduced_pos = [self.reduce_single(arg) for arg in args.arguments]
+ for key in args.kwargs.keys():
+ if not isinstance(key, str):
+ raise InvalidArguments('Line %d: keyword argument name is not a string.' % args.lineno())
+ reduced_kw = {}
+ return (reduced_pos, reduced_kw)
def method_call(self, node):
object_name = node.object_name.get_value()
diff --git a/nodes.py b/nodes.py
index 72b1edd..b1d26ee 100644
--- a/nodes.py
+++ b/nodes.py
@@ -170,13 +170,26 @@ class Arguments(Statement):
def __init__(self, lineno):
Statement.__init__(self, lineno)
self.arguments = []
-
+ self.kwargs = {}
+ self.order_error = False
+
def prepend(self, statement):
self.arguments = [statement] + self.arguments
- def __len__(self):
+ def set_kwarg(self, name, value):
+ if self.num_args() > 0:
+ self.order_error = True
+ self.kwargs[name.get_value()] = value
+
+ def num_args(self):
return len(self.arguments)
+ def num_kwargs(self):
+ return len(self.kwargs)
+
+ def __len__(self):
+ return self.num_args() # Fixme
+
def statement_from_expression(expr):
if isinstance(expr, AtomExpression):
return AtomStatement(expr.value, expr.lineno())
diff --git a/test cases/1 trivial/builder.txt b/test cases/1 trivial/builder.txt
index dc2a992..34264c5 100644
--- a/test cases/1 trivial/builder.txt
+++ b/test cases/1 trivial/builder.txt
@@ -1,3 +1,7 @@
project('trivial test', 'c')
-exe = executable('trivialprog', 'trivial.c')
+
+sources = 'trivial.c'
+
+exe = executable('trivialprog', sources : sources)
+
add_test('runtest', exe)