The following is how to create a basic debugger object in AS3. I have done my best to make it so that it is AS2 compatible, but certain (minor) adjustments will have to be made to make all of the code work.


The first step is finding a way to convert Strings into functions. That way, you can fire arbitrary commands at will and therefore use this as a front-end for any number of devices. While this is written as a "debugger", its functionality allows for any number of implementations, such as (and the second part of this article will cover this) a command prompt interface. I'd also imagine that this might be implemented in a database UI, but that is neither here nor there. For now, we'll start with the task at hand.


private var origin:Object; //This object exists as an easy way to keep track of the root for AS2 & 3 implementations.
// For now, you have to pass the root into the debugger for a reference.

public function debugger(obj:Object){
//_root for AS2 origin = obj;
}

/**
* This is the heart and soul of the debugger.
* It will allow an arbitrary function to be fired off at run time.
* @param A string formatted ex: Function(param1,param2,param3...)
*/


public function runString(str:String):Object {
var left:Number = functionText.indexOf('(');
var fStr:String = (functionText.substr(0,left));
var right:Number = functionText.lastIndexOf(')') - 1; // Get the values between the parenthesis.
var paramText:String = functionText.substr(left + 1,(right-left));
var parameters:Array = new Array();
parameters = paramText.split(',');
var appedPar:Array = new Array();
for (var i:Number = 0; i<PARAMETERS.LENGTH;
 var ans = (parameters[i]); appedPar.push(ans);
}
// Function(obj).apply takes two parameters. The scope and the parameters array.// if the function is Stage.foo.bar(), then the scope of bar is foo.var scope:Object = (fStr.indexOf('.') <= 0)?this:returnType( functionText.substr(0, functionText.lastIndexOf('.')));var obj:Object = (returnType(fStr));// if AS2=> obj.apply()return obj.apply(scope, appedPar);}[\as]


So far so good, but there is one small problem. Everything is typed String. So if you want to run:

[as]Stage.foo.bar(baz,7)


you get this instead:

'Stage.foo.bar'('baz','7');


Hardly ideal. This leads to the next function:


/**
* Given a string, this function will find its type and eval it
* @param the string to evaluate.
*/

private function returnType(obj:String):* {
if ((obj.substr(0,1) == '"') || (obj.substr(0,1) == '\'')){
// If the string is enclosed by quotes, it is a String
var ans1:String = obj.slice(1, (obj.length-1));
return ans1;
} else if ((obj == 'true')||(obj == 'false') || typeof(obj) == 'boolean') {
var ans2:Boolean = Boolean((String(obj) == 'true'));
return ans2;
} else if (!isNaN(Number(obj))) {
var ans3:Number = Number(obj);
return ans3;
} else if (ans == undefined){
var ans =( findObj(obj) != null)? findObj(obj) : obj;
return ans;
}
return null;
}
[as]

You might have noticed my cheat -- there is a 'findObj' function in there. This is because, if the object contained in the String is not one of the simple types, there needs to be some function which goes and 'finds' the object. In this case, it is simply going through the String as if it were an object's path.

[as]
/**
* Given a String, it returns the object the String is pointing to.
* @param evalStr the String to parse.
*/

private function findObj(evalStr):Object{
// To get to an object with a given String, first break the string up into an Array.
var strArray:Array = evalStr.split('
.');
if (strArray.length == 1) return origin[evalStr];
// Next, to start at origin, remove the first value in the array and create the return object

var obj:Object = origin;
for (var i:int = 0; i<STRARRAY.LENGTH;
 var val:String = strArray[i];
obj = obj[ val ]
}
return obj;
}


Unfortunately, while this will work for all objects which exist on the root or a child of the root, it has difficulties with global functions like trace. This means that, in order to access the Top Level functions, you will need to write some form of wrapper around them such as this function on the root:
function say(a){trace(a)}


Of course, there is much more than this. The "next" article discusses a basic console which I've built as an implimentation.