mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-15 04:54:29 +00:00
Preliminary typechecking version of objj_msgSend, and preprocessor support.
This commit is contained in:
1 parent
a5a43de26e
commit
9b99457871
2 files changed
+100
-4
No files matched your search
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
Reference in new issue
Block a user