Access variables through functions that do error checking.

pull/15/head
Jussi Pakkanen 12 years ago
parent f0cec5bd79
commit 261419aff3
  1. 69
      interpreter.py
  2. 1
      shellgenerator.py
  3. 8
      test cases/24 target arg/builder.txt
  4. 9
      test cases/24 target arg/func.c
  5. 13
      test cases/24 target arg/prog.cc

@ -17,7 +17,7 @@
import parser
import nodes
import environment
import os
import os, sys, platform
class InterpreterException(Exception):
pass
@ -38,6 +38,25 @@ class InterpreterObject():
return self.methods[method_name](args)
raise InvalidCode('Unknown method "%s" in object.' % method_name)
# This currently returns data for the current environment.
# It should return info for the target host.
class Host(InterpreterObject):
def __init__(self):
InterpreterObject.__init__(self)
def get_ptrsize(self):
if sys.maxsize > 2**32:
return 64
return 32
def get_name(self):
return platform.system().lower()
def is_little_endian(self):
return sys.byteorder == 'little'
class IncludeDirs(InterpreterObject):
def __init__(self, curdir, dirs):
InterpreterObject.__init__(self)
@ -132,15 +151,20 @@ class BuildTarget(InterpreterObject):
'install': self.install_method,
'pch' : self.pch_method,
'add_include_dirs': self.add_include_dirs_method,
'add_compiler_args' : self.add_compiler_args_method,
})
self.link_targets = []
self.filename = 'no_name'
self.need_install = False
self.pch = []
self.extra_args = {}
def get_filename(self):
return self.filename
def get_extra_args(self, language):
return self.extra_args.get(language, [])
def get_dependencies(self):
return self.link_targets
@ -199,6 +223,17 @@ class BuildTarget(InterpreterObject):
if not isinstance(a, IncludeDirs):
raise InvalidArguments('Include directory to be added is not an include directory object.')
self.include_dirs += args
def add_compiler_args_method(self, args):
for a in args:
if not isinstance(a, str):
raise InvalidArguments('A non-string passed to compiler args.')
language = args[0]
flags = args[1:]
if language in self.extra_args:
self.extra_args[language] += flags
else:
self.extra_args[language] = flags
class Executable(BuildTarget):
def __init__(self, name, subdir, sources, environment):
@ -244,6 +279,8 @@ class Interpreter():
self.ast = parser.build_ast(code)
self.sanity_check_ast()
self.variables = {}
self.builtin = {}
self.builtin['host'] = Host()
self.environment = build.environment
self.build_func_dict()
self.subdir = ''
@ -292,6 +329,18 @@ class Interpreter():
self.evaluate_statement(cur)
i += 1 # In THE FUTURE jump over blocks and stuff.
def get_variable(self, varname):
if varname in self.builtin:
return self.builtin[varname]
if varname in self.variables:
return self.variables[varname]
raise InvalidCode('Line %d: unknown variable "%s".' % varname)
def set_variable(self, varname, variable):
if varname in self.builtin:
raise InvalidCode('Tried to overwrite internal variable "%s"' % varname)
self.variables[varname] = variable
def evaluate_statement(self, cur):
if isinstance(cur, nodes.FunctionCall):
return self.function_call(cur)
@ -306,10 +355,7 @@ class Interpreter():
elif isinstance(cur, nodes.IfStatement):
return self.evaluate_if(cur)
elif isinstance(cur, nodes.AtomStatement):
varname = cur.get_value()
if varname in self.variables:
return self.variables[varname]
raise InvalidCode('Line %d: unknown variable "%s".' % (cur.lineno(), varname))
return self.get_variable(cur.get_value())
elif isinstance(cur, nodes.Comparison):
return self.evaluate_comparison(cur)
elif isinstance(cur, nodes.ArrayStatement):
@ -459,7 +505,6 @@ class Interpreter():
name = args[0]
sources = []
for s in args[1:]:
print(s)
if not self.environment.is_header(s):
sources.append(s)
if len(sources) == 0:
@ -498,7 +543,7 @@ class Interpreter():
raise InvalidCode('Line %d: Can not assign None to variable.' % node.lineno())
if not self.is_assignable(value):
raise InvalidCode('Line %d: Tried to assign an invalid value to variable.' % node.lineno())
self.variables[var_name] = value
self.set_variable(var_name, value)
return value
def reduce_arguments(self, args):
@ -506,9 +551,7 @@ class Interpreter():
reduced = []
for arg in args.arguments:
if isinstance(arg, nodes.AtomExpression) or isinstance(arg, nodes.AtomStatement):
if arg.value not in self.variables:
raise InvalidCode('Line %d: variable "%s" is not set' % (arg.lineno(), arg.value))
r = self.variables[arg.value]
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):
@ -525,9 +568,7 @@ class Interpreter():
object_name = node.object_name.get_value()
method_name = node.method_name.get_value()
args = node.arguments
if not object_name in self.variables:
raise InvalidArguments('Line %d: unknown variable "%s".' % (node.lineno(), object_name))
obj = self.variables[object_name]
obj = self.get_variable(object_name)
if not isinstance(obj, InterpreterObject):
raise InvalidArguments('Line %d: variable "%s" is not callable.' % (node.lineno(), object_name))
return obj.method_call(method_name, self.reduce_arguments(args))

@ -210,6 +210,7 @@ echo Run compile.sh before this or bad things will happen.
commands = []
commands += compiler.get_exelist()
commands += self.build.get_global_flags(compiler)
commands += target.get_extra_args(compiler.get_language())
commands += compiler.get_debug_flags()
commands += compiler.get_std_warn_flags()
commands += compiler.get_compile_only_flags()

@ -0,0 +1,8 @@
project('local arg test', 'c++', 'c')
exe1 = executable('prog', 'prog.cc', 'func.c')
exe1.add_compiler_args('c', '-DCTHING')
exe1.add_compiler_args('c++', '-DCXXTHING')
add_test('prog1', exe1)

@ -0,0 +1,9 @@
#ifndef CTHING
#error "Local argument not set"
#endif
#ifdef CXXTHING
#error "Wrong local argument set"
#endif
int func() { return 0; }

@ -0,0 +1,13 @@
#ifdef CTHING
#error "Wrong local argument set"
#endif
#ifndef CXXTHING
#error "Local argument not set"
#endif
extern "C" int func();
int main(int argc, char **argv) {
return func();
}
Loading…
Cancel
Save