Edit: You can get the full source here: http://pastebin.com/m26693
Edit again: I added some highlights to the pastebin page. http://pastebin.com/m10f8d239
I'm probably going to regret asking such a long question, but I'm stumped with this bug and I could use some guidance. You're going to have to run this code (edit: not anymore. I couldn't include all of the code -- it was truncated) to help in order to really see what's going on, unless you're God or something, then by all means figure it out without running it. Actually I kind of hope that I can explain it well enough so that's not necessary, and I do apologize if I don't accomplish that.
First I'll give you some output. (Edit: There's new output below)
argc 1 [<__main__.RESULT instance at 0x94f91ec>]
(<__main__.RESULT instance at 0x9371f8c>, <__main__.RESULT instance at 0x94f91ec>)
None
bar
internal error: unknown result type 0
argc 1 [<__main__.RESULT instance at 0x94f92ac>]
(<__main__.RESULT instance at 0x94f91ac>, <__main__.RESULT instance at 0x94f92ac>)
None
bar
internal error: unknown result type 0
argc 1 [<__main__.RESULT instance at 0x94f91ec>]
(<__main__.RESULT instance at 0x94f91ec>,)
String: 'bar'
We have 3 divisions in the output. Notice that argc is always 1. At the point where that is printed, an argument list has been built to be passed to a plugin (Plugins are simply commands in the expression interpreter. Most of this code is the expression interpreter.) The list of a single RESULT instance representation that follows argc is the argument list. The next line is the argument list once it reaches the Python method being called. Notice it has two arguments at this point. The first of these two is trash. The second one is what I wanted. However, as you can see on the lines starting "argc 1" that argument list is always 1 RESULT wide. Where's the stray argument coming from?
Like I said, there are 3 divisions in the output. The first division is a class by itself. The second division is a subclassed class. And the third division is no class/instance at all. The only division that outputs what I expected is the 3rd. Notice it has 1 argument member both before the call and within the call, and the last line is the intended output. It simply echoes/returns the argument "bar".
Are there any peculiarities with variable argument lists that I should be aware of? What I mean is the following:
def foo(result, *argv):
print argv[0]
I really think the bug has something to do with this, because that is where the trash seems to come from -- in between the call and the execution arrival in the method.
Edit: Ok, so they limit the size of these questions. :) I'll try my best to show what's going on. Here's the relevant part of EvalTree. Note that there's only 2 divisions in this code. I messed up that other file and deleted it.
def EvalTree(self, Root):
type = -1
number = 0.0
freeme = 0
if Root.Token == T_NUMBER or Root.Token == T_STRING:
return 0
elif Root.Token == T_VARIABLE:
self.CopyResult(Root.Result, Root.Variable.value)
return 0
elif Root.Token == T_FUNCTION:
argc = Root.Children
param = resizeList([], argc, RESULT)
print "argc", argc
for i in range(argc):
self.EvalTree(Root.Child[i])
param[i] = Root.Child[i].Result
self.DelResult(Root.Result)
Root.Function.func(Root.Result, *param) # I should have never ever programmed Lua ever.
return 0
Here's the Plugin's class.
class Foo:
def __init__(self, visitor):
visitor.AddFunction("foo", -1, self.foo)
def foo(self, result, *argv):
print argv
Here's where it's all executed.
if __name__ == "__main__":
evaluator = Evaluator()
expression = "foo2('bar')"
#expression = "uptime('test')"
evaluator.SetVariableString("test", "Foo")
def func(self, result, *arg1):
print arg1
evaluator.SetResult(result, R_STRING, evaluator.R2S(arg1[0]))
evaluator.AddFunction('foo2', -1, func)
result = RESULT(0, 0, 0, None)
tree = evaluator.Compile(expression)
if tree != -1:
evaluator.Eval(tree, result)
if result.type == R_NUMBER:
print "Number: %g" % (evaluator.R2N(result))
elif result.type == R_STRING:
print "String: '%s'" % (result.string) #(evaluator.R2S(result))
elif result.type == (R_NUMBER | R_STRING):
print "String: '%s' Number: (%g)" % (evaluator.R2S(result), evaluator.R2N(result))
else:
print "internal error: unknown result type %d" % (result.type)
expression = "foo('test')"
result = RESULT(0, 0, 0, None)
tree = evaluator.Compile(expression)
if tree != -1:
evaluator.Eval(tree, result)
if result.type == R_NUMBER:
print "Number: %g" % (evaluator.R2N(result))
elif result.type == R_STRING:
print "String: '%s'" % (result.string) #(evaluator.R2S(result))
elif result.type == (R_NUMBER | R_STRING):
print "String: '%s' Number: (%g)" % (evaluator.R2S(result), evaluator.R2N(result))
else:
print "internal error: unknown result type %d" % (result.type)
This is the new output:
argc 1
(<__main__.RESULT instance at 0x9ffcf4c>,)
String: 'bar'
argc 1
(<__main__.RESULT instance at 0xa0030cc>, <__main__.RESULT instance at 0xa0030ec>)
internal error: unknown result type 0