From 0a31afd672f10d1d996fca1915551b647b8489e2 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 19 Nov 2016 19:48:12 +0200 Subject: [PATCH] Embark on a journey to create a rewrite tool. --- mesonast.py | 31 ++++++++++++++++++++ mesonbuild/astinterpreter.py | 26 +++++++++++++++++ mesonbuild/interpreter.py | 34 +++++----------------- mesonbuild/interpreterbase.py | 54 +++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 27 deletions(-) create mode 100755 mesonast.py create mode 100644 mesonbuild/astinterpreter.py create mode 100644 mesonbuild/interpreterbase.py diff --git a/mesonast.py b/mesonast.py new file mode 100755 index 000000000..215f1fa32 --- /dev/null +++ b/mesonast.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. + +# This tool is used to manipulate an existing Meson build definition. +# +# - add a file to a target +# - remove files from a target +# - move targets +# - reindent? + +import mesonbuild.astinterpreter + +if __name__ == '__main__': + source_root = 'test cases/common/1 trivial' + ast = mesonbuild.astinterpreter.AstInterpreter(source_root, '') + ast.dump() \ No newline at end of file diff --git a/mesonbuild/astinterpreter.py b/mesonbuild/astinterpreter.py new file mode 100644 index 000000000..7e221d154 --- /dev/null +++ b/mesonbuild/astinterpreter.py @@ -0,0 +1,26 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. + +from . import interpreterbase + +class AstInterpreter(interpreterbase.InterpreterBase): + def __init__(self, source_root, subdir): + super().__init__(source_root, subdir) + + def dump(self): + self.load_root_meson_file() + print('AST here') \ No newline at end of file diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ac04b1a54..bc2717ec2 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -22,6 +22,8 @@ from . import optinterpreter from . import compilers from .wrap import wrap from . import mesonlib +from mesonbuild.interpreterbase import InterpreterBase +from mesonbuild.interpreterbase import InterpreterException, InvalidArguments, InvalidCode import os, sys, subprocess, shutil, uuid, re from functools import wraps @@ -31,15 +33,6 @@ import copy run_depr_printed = False -class InterpreterException(mesonlib.MesonException): - pass - -class InvalidCode(InterpreterException): - pass - -class InvalidArguments(InterpreterException): - pass - # Decorators for method calls. def check_stringlist(a, msg='Arguments must be strings.'): @@ -1144,16 +1137,15 @@ class MesonMain(InterpreterObject): return args[1] raise InterpreterException('Unknown cross property: %s.' % propname) -class Interpreter(): +class Interpreter(InterpreterBase): def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects'): + super().__init__(build.environment.get_source_dir(), subdir) self.build = build self.environment = build.environment self.coredata = self.environment.get_coredata() self.backend = backend self.subproject = subproject - self.subdir = subdir - self.source_root = build.environment.get_source_dir() self.subproject_dir = subproject_dir option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') if os.path.exists(option_file): @@ -1161,19 +1153,7 @@ class Interpreter(): self.build.environment.cmd_line_options.projectoptions) oi.process(option_file) self.build.environment.merge_options(oi.options) - mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename) - if not os.path.isfile(mesonfile): - raise InvalidArguments('Missing Meson file in %s' % mesonfile) - with open(mesonfile, encoding='utf8') as mf: - code = mf.read() - if len(code.strip()) == 0: - raise InvalidCode('Builder file is empty.') - assert(isinstance(code, str)) - try: - self.ast = mparser.Parser(code).parse() - except mesonlib.MesonException as me: - me.file = environment.build_filename - raise me + self.load_root_meson_file() self.sanity_check_ast() self.variables = {} self.builtin = {'meson': MesonMain(build, self)} @@ -1201,7 +1181,7 @@ class Interpreter(): self.build_def_files = [os.path.join(self.subdir, environment.build_filename)] def build_func_dict(self): - self.funcs = {'project' : self.func_project, + self.funcs.update({'project' : self.func_project, 'message' : self.func_message, 'error' : self.func_error, 'executable': self.func_executable, @@ -1246,7 +1226,7 @@ class Interpreter(): 'assert': self.func_assert, 'environment' : self.func_environment, 'join_paths' : self.func_join_paths, - } + }) def parse_project(self): """ diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py new file mode 100644 index 000000000..6c11ff76d --- /dev/null +++ b/mesonbuild/interpreterbase.py @@ -0,0 +1,54 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. + +from . import mparser +from . import mesonlib +from . import environment + +import os + +class InterpreterException(mesonlib.MesonException): + pass + +class InvalidCode(InterpreterException): + pass + +class InvalidArguments(InterpreterException): + pass + + + +class InterpreterBase: + def __init__(self, source_root, subdir): + self.source_root = source_root + self.funcs = {} + self.subdir = subdir + + def load_root_meson_file(self): + mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename) + if not os.path.isfile(mesonfile): + raise InvalidArguments('Missing Meson file in %s' % mesonfile) + with open(mesonfile, encoding='utf8') as mf: + code = mf.read() + if len(code.strip()) == 0: + raise InvalidCode('Builder file is empty.') + assert(isinstance(code, str)) + try: + self.ast = mparser.Parser(code).parse() + except mesonlib.MesonException as me: + me.file = environment.build_filename + raise me