Preliminary typechecking version of objj_msgSend, and preprocessor support.

This commit is contained in:
tlrobinson committed 2009-07-20 18:16:17 -07:00
1 parent a5a43de26e
commit 9b99457871
2 files changed
+100 -4

No files matched your search

+19 -4
View File
@@ -578,12 +578,15 @@ objj_preprocessor.prototype.method = function(tokens)
var buffer = new objj_stringBuffer(),
token,
selector = "",
parameters = [];
parameters = [],
types = [null];
while((token = tokens.skip_whitespace()) && token != TOKEN_OPEN_BRACE)
{
if (token == TOKEN_COLON)
{
var type = "";
// Colons are part of the selector name
selector += token;
@@ -592,18 +595,30 @@ objj_preprocessor.prototype.method = function(tokens)
if (token == TOKEN_OPEN_PARENTHESIS)
{
// Swallow parameter/return type. Perhaps later we can use this for debugging?
while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ;
while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS)
type += token;
token = tokens.skip_whitespace();
}
// Add the type. If it's empty, add null instead.
types[parameters.length+1] = type || null;
// Since this follows a colon, this must be the parameter name.
parameters[parameters.length] = token;
}
else if (token == TOKEN_OPEN_PARENTHESIS)
{
var type = "";
// Since :( is handled above, this must be the return type, just swallow it.
while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ;
while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS)
type += token;
// types[0] is the return argument
types[0] = type || null;
}
// Argument list ", ..."
else if (token == TOKEN_COMMA)
@@ -640,7 +655,7 @@ objj_preprocessor.prototype.method = function(tokens)
CONCAT(buffer, ")\n{ with(self)\n{");
CONCAT(buffer, this.preprocess(tokens, NULL, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE));
CONCAT(buffer, "}\n})");
CONCAT(buffer, "}\n},"+types.toSource()+")");
return buffer;
}
+81
View File
@@ -542,3 +542,84 @@ function sel_registerName(aName)
{
return aName;
}
// Type checking version of objj_msgSend:
function objj_msgSendTypeCheck(/*id*/ aReceiver, /*SEL*/ aSelector)
{
if (aReceiver == nil)
return nil;
CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aReceiver.isa, aSelector);
var types = method.types;
for (var i = 2; i < arguments.length; i++)
{
try
{
runtimeTypeCheck(types[i-1], arguments[i]);
}
catch (e)
{
objj_fprintf(warning_stream, "Type check failure: "+
"aReceiver="+String(aReceiver).substring(0,100)+", "+
"aSelector="+String(aSelector).substring(0,100)+", "+
"argument #"+(i-2)+": " + e);
}
}
var result = implementation.apply(aReceiver, arguments);
try
{
runtimeTypeCheck(types[0], result);
}
catch (e)
{
objj_fprintf(warning_stream, "Type check failure: "+
"aReceiver="+String(aReceiver).substring(0,100)+", "+
"aSelector="+String(aSelector).substring(0,100)+", "+
"return value: " + e);
}
return result;
}
function runtimeTypeCheck(typeName, actual)
{
var objjClass;
if (!typeName)
{
return;
}
if (typeName === "id")
{
return;
}
else if (typeName === "void")
{
if (actual === undefined)
return;
}
else if (objjClass = objj_getClass(typeName))
{
if (actual && actual.isa)
{
var theClass = actual.isa;
for(; theClass; theClass = theClass.super_class)
if (theClass === objjClass)
return;
}
}
else
{
return;
}
throw("Expected " + typeName + ", was [" + actual +"]");
}
objj_msgSend = objj_msgSendTypeCheck;