mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
simple auto-generated caller more or less works now
This commit is contained in:
parent
2ceb6fc6ef
commit
ec8a8b1500
@ -152,6 +152,16 @@ def getUnLockGetter(varType, name, funcName):
|
||||
sys.stderr.write("ERROR: getUnLockGetter: Unknown type '"+varType+"' for "+funcName+":"+name+"\n")
|
||||
exit(1)
|
||||
|
||||
def getGetter(varType, name, funcName):
|
||||
if varType=="float": return "jsvGetFloat("+name+")"
|
||||
if varType=="int": return "jsvGetInteger("+name+")"
|
||||
if varType=="int32": return "(int)jsvGetInteger("+name+")"
|
||||
if varType=="bool": return "jsvGetBool("+name+")"
|
||||
if varType=="pin": return "jshGetPinFromVar("+name+")"
|
||||
if varType=="JsVar" or varType=="JsVarName": return name
|
||||
sys.stderr.write("ERROR: getGetter: Unknown type '"+varType+"' for "+funcName+":"+name+"\n")
|
||||
exit(1)
|
||||
|
||||
def getCreator(varType, value, funcName):
|
||||
if varType=="float": return "jsvNewFromFloat("+value+")"
|
||||
if varType=="int": return "jsvNewFromInteger("+value+")"
|
||||
@ -161,6 +171,70 @@ def getCreator(varType, value, funcName):
|
||||
sys.stderr.write("ERROR: getCreator: Unknown type '"+varType+"'"+"' for "+funcName+"\n")
|
||||
exit(1)
|
||||
|
||||
def toArgumentType(argName):
|
||||
if argName=="": return "JSWAT_VOID";
|
||||
if argName=="JsVar": return "JSWAT_JSVAR";
|
||||
if argName=="JsVarName": return "JSWAT_JSVARNAME";
|
||||
if argName=="JsVarArray": return "JSWAT_ARGUMENT_ARRAY";
|
||||
if argName=="bool": return "JSWAT_BOOL";
|
||||
if argName=="pin": return "JSWAT_PIN";
|
||||
if argName=="int32": return "JSWAT_INT32";
|
||||
if argName=="int": return "JSWAT_JSVARINT";
|
||||
if argName=="float": return "JSWAT_JSVARFLOAT";
|
||||
sys.stderr.write("ERROR: toArgumentType: Unknown argument name "+argName+"\n")
|
||||
exit(1)
|
||||
|
||||
def toCType(argName):
|
||||
if argName=="": return "void";
|
||||
if argName=="JsVar": return "JsVar*";
|
||||
if argName=="JsVarName": return "JsVar*";
|
||||
if argName=="JsVarArray": return "JsVar*";
|
||||
if argName=="bool": return "bool";
|
||||
if argName=="pin": return "Pin";
|
||||
if argName=="int32": return "int";
|
||||
if argName=="int": return "JsVarInt";
|
||||
if argName=="float": return "JsVarFloat";
|
||||
sys.stderr.write("ERROR: toCType: Unknown argument name "+argName+"\n")
|
||||
exit(1)
|
||||
|
||||
def hasThis(func):
|
||||
return func["type"]=="property" or func["type"]=="method"
|
||||
|
||||
def getParams(func):
|
||||
params = []
|
||||
if hasThis(func): params.append(["","JsVar",""]);
|
||||
if "params" in func:
|
||||
for param in func["params"]:
|
||||
params.append(param)
|
||||
return params
|
||||
|
||||
def getResult(func):
|
||||
result = [ "", "Description" ]
|
||||
if "return" in func: result = func["return"]
|
||||
return result
|
||||
|
||||
|
||||
def getArgumentSpecifier(jsondata):
|
||||
params = getParams(jsondata)
|
||||
result = getResult(jsondata);
|
||||
s = [ toArgumentType(result[0]) ]
|
||||
n = 1
|
||||
for param in params:
|
||||
s.append("("+toArgumentType(param[1])+" << (JSWAT_BITS*"+str(n)+"))");
|
||||
n=n+1
|
||||
return " | ".join(s);
|
||||
|
||||
|
||||
def getCDeclaration(jsondata):
|
||||
params = getParams(jsondata)
|
||||
result = getResult(jsondata);
|
||||
s = [ ]
|
||||
for param in params:
|
||||
s.append(toCType(param[1]));
|
||||
return toCType(result[0])+" (*)("+",".join(s)+")";
|
||||
|
||||
|
||||
|
||||
def codeOutFunctionObject(indent, obj):
|
||||
codeOut(indent+"// Object "+obj["name"]+" ("+obj["filename"]+")")
|
||||
if "#if" in obj: codeOut(indent+"#if "+obj["#if"]);
|
||||
@ -178,8 +252,16 @@ def codeOutFunction(indent, func):
|
||||
name = name + func["name"]
|
||||
print name
|
||||
codeOut(indent+"// "+name+" ("+func["filename"]+")")
|
||||
hasThis = func["type"]=="property" or func["type"]=="method"
|
||||
if ("generate" in func) or ("generate_full" in func):
|
||||
if ("generate" in func):
|
||||
if hasThis(func):
|
||||
codeOut(indent+"argArray[0] = jsvLockAgain(parent);");
|
||||
codeOut(indent+"int argCount = jspParseFunctionIntoArray(&argArray[1], sizeof(argArray)/sizeof(argArray[0])-1)+1;");
|
||||
else:
|
||||
codeOut(indent+"int argCount = jspParseFunctionIntoArray(argArray, sizeof(argArray)/sizeof(argArray[0]));");
|
||||
codeOut(indent+"JsVar *_r = jswCallFunction("+func["generate"]+", "+getArgumentSpecifier(func)+", argArray, argCount);");
|
||||
codeOut(indent+"while (argCount--) jsvUnLock(argArray[argCount]);");
|
||||
codeOut(indent+"return _r;");
|
||||
elif ("generate_full" in func):
|
||||
argNames = ["a","b","c","d"];
|
||||
params = []
|
||||
if "params" in func: params = func["params"]
|
||||
@ -217,26 +299,11 @@ def codeOutFunction(indent, func):
|
||||
print "ERROR: codeOutFunction unknown number of args "+str(len(params))
|
||||
exit(1)
|
||||
|
||||
if "generate" in func:
|
||||
commandargs = [];
|
||||
if hasThis:
|
||||
commandargs.append("parent")
|
||||
if "needs_parentName" in func:
|
||||
commandargs.append("parentName")
|
||||
for param in params:
|
||||
if param[1]=="JsVar" or param[1]=="JsVarName" or param[1]=="JsVarArray":
|
||||
commandargs.append(param[0]);
|
||||
else:
|
||||
commandargs.append(getUnLockGetter(param[1], param[0], func["name"]));
|
||||
command = func["generate"]+"("+ ', '.join(commandargs) +")";
|
||||
else:
|
||||
command = func["generate_full"];
|
||||
|
||||
command = func["generate_full"];
|
||||
if "return" in func:
|
||||
codeOut(indent+"JsVar *_r = " + getCreator(func["return"][0], command, func["name"])+";");
|
||||
else:
|
||||
codeOut(indent+command+";");
|
||||
|
||||
# note: generate_full doesn't use commandargs, so doesn't unlock
|
||||
for param in params:
|
||||
if "generate_full" in func or param[1]=="JsVar" or param[1]=="JsVarName" or param[1]=="JsVarArray":
|
||||
@ -295,7 +362,7 @@ print ""
|
||||
print ""
|
||||
|
||||
codeOut('// Automatically generated wrapper file ')
|
||||
codeOut('// Generated by scripts/build_jsfunctions.py');
|
||||
codeOut('// Generated by scripts/build_jswrapper.py');
|
||||
codeOut('');
|
||||
codeOut('#include "jswrapper.h"');
|
||||
for include in includes:
|
||||
@ -313,6 +380,7 @@ codeOut('#define CMP3(var, a,b,c) (((*(unsigned int*)&(var))&0x00FFFFFF)==CH4(a,
|
||||
codeOut('#define CMP4(var, a,b,c,d) ((*(unsigned int*)&(var))==CH4(a,b,c,d))');
|
||||
codeOut('');
|
||||
codeOut('JsVar *jswHandleFunctionCall(JsVar *parent, JsVar *parentName, const char *name) {')
|
||||
codeOut(' JsVar *argArray[16];')
|
||||
codeOut(' if (parent) {')
|
||||
codeOut(' // ------------------------------------------ METHODS ON OBJECT')
|
||||
if "parent" in tree:
|
||||
@ -458,3 +526,40 @@ codeOut('}')
|
||||
|
||||
codeOut('')
|
||||
codeOut('')
|
||||
|
||||
codeOut("/** Call a function with the given argument specifiers */")
|
||||
codeOut('JsVar *jswCallFunction(void *function, unsigned int argumentSpecifier, JsVar **paramData, int paramCount) {')
|
||||
argSpecs = []
|
||||
for jsondata in jsondatas:
|
||||
# if "generate" in jsondata:
|
||||
argSpec = getArgumentSpecifier(jsondata)
|
||||
if not argSpec in argSpecs:
|
||||
codeOut(' if (argumentSpecifier == ('+argSpec+')) {')
|
||||
|
||||
params = getParams(jsondata)
|
||||
result = getResult(jsondata);
|
||||
|
||||
n = 0
|
||||
argList = [ ]
|
||||
for param in params:
|
||||
if param[1]=="JsVarArray":
|
||||
argList.append("jsvNewArray(¶mData["+str(n)+"], paramCount-"+str(n)+")");
|
||||
else:
|
||||
argList.append(getGetter(param[1] , "paramData["+str(n)+"]", "jswCallFunction"));
|
||||
n = n+1;
|
||||
|
||||
|
||||
if result[0]!="":
|
||||
codeOut(' return '+getCreator(result[0], '(('+getCDeclaration(jsondata)+')function)('+', '.join(argList)+')',"jswCallFunction")+';')
|
||||
else:
|
||||
codeOut(' (('+getCDeclaration(jsondata)+')function)('+', '.join(argList)+');')
|
||||
codeOut(' return 0/*undefined*/;')
|
||||
codeOut(' }')
|
||||
|
||||
argSpecs.append(argSpec)
|
||||
codeOut(' jsError("No caller for argument specifier %d", argumentSpecifier);')
|
||||
codeOut(' return 0;')
|
||||
codeOut('}')
|
||||
|
||||
codeOut('')
|
||||
codeOut('')
|
||||
|
||||
@ -41,13 +41,16 @@ if silent:
|
||||
# "needs_parentName":true, // optional - if for a method, this makes the first 2 args parent+parentName (not just parent)
|
||||
# "generate_full|generate|wrap" : "*(JsVarInt*)&x",
|
||||
# "description" : " Convert the floating point value given into an integer representing the bits contained in it",
|
||||
# "params" : [ [ "x" , "float|int|JsVar|JsVarName|JsVarArray", "A floating point number"] ],
|
||||
# "params" : [ [ "x" , "float|int|int32|bool|pin|JsVar|JsVarName|JsVarArray", "A floating point number"] ],
|
||||
# // float - parses into a JsVarFloat which is passed to the function
|
||||
# // int - parses into a JsVarInt which is passed to the function
|
||||
# // int32 - parses into a 32 bit int
|
||||
# // bool - parses into a boolean
|
||||
# // pin - parses into a pin
|
||||
# // JsVar - passes a JsVar* to the function (after skipping names)
|
||||
# // JsVarName - passes a JsVar* to the function (WITHOUT skipping names)
|
||||
# // JsVarArray - parses this AND ANY SUBSEQUENT ARGUMENTS into a JsVar of type JSV_ARRAY. THIS IS ALWAYS DEFINED, EVEN IF ZERO LENGTH. Currently it must be the only parameter
|
||||
# "return" : ["int|float", "The integer representation of x"],
|
||||
# "return" : ["int|float|JsVar", "The integer representation of x"],
|
||||
# "no_create_links":1 // optional - if this is set then hyperlinks are not created when this name is mentioned (good example = bit() )
|
||||
# "not_real_object" : "anything", // optional - for classes, this means we shouldn't treat this as a built-in object, as internally it isn't stored in a JSV_OBJECT
|
||||
# "prototype" : "Object", // optional - for classes, this is what their prototype is. It's particlarly helpful if not_real_object, because there is no prototype var in that case
|
||||
|
||||
@ -24,10 +24,12 @@ typedef enum {
|
||||
JSNAT_FINISH = 0, // no argument
|
||||
JSNAT_VOID = 0, // Only for return values
|
||||
JSNAT_JSVAR, // standard variable
|
||||
JSNAT_JSVARNAME, // variable without the name being stripped off
|
||||
JSNAT_ARGUMENT_ARRAY, // a JsVar array containing all subsequent arguments
|
||||
JSNAT_BOOL, // boolean
|
||||
JSNAT_INT16, // 16 bit int
|
||||
JSNAT_INT32, // 32 bit int
|
||||
JSNAT_PIN, // A pin
|
||||
JSNAT_JSVARINT, // 64 bit int
|
||||
JSNAT_JSVARFLOAT, // 64 bit float
|
||||
JSNAT__LAST = JSNAT_JSVARFLOAT,
|
||||
|
||||
@ -377,6 +377,20 @@ NO_INLINE JsVar *jspParseFunctionAsArray() {
|
||||
return arr;
|
||||
}
|
||||
|
||||
/// parse a function with any number of arguments into the given array, and return the size
|
||||
NO_INLINE int jspParseFunctionIntoArray(JsVar **array, int arraySize) {
|
||||
JSP_MATCH(LEX_ID);
|
||||
int p = 0;
|
||||
JSP_MATCH_WITH_RETURN('(', p);
|
||||
while (!JSP_HAS_ERROR && execInfo.lex->tk!=')' && execInfo.lex->tk!=LEX_EOF && p<arraySize) {
|
||||
array[p++] = jsvSkipNameAndUnLock(jspeAssignmentExpression());
|
||||
if (execInfo.lex->tk!=')') JSP_MATCH_WITH_RETURN(',', p);
|
||||
}
|
||||
|
||||
JSP_MATCH_WITH_RETURN(')', p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// we return a value so that JSP_MATCH can return 0 if it fails (if we pass 0, we just parse all args)
|
||||
|
||||
@ -114,6 +114,7 @@ bool jspParseVariableName(); ///< parse single variable name
|
||||
bool jspParseEmptyFunction(); ///< parse function with no arguments
|
||||
JsVar *jspParseSingleFunction(); ///< parse function with a single argument, return its value (no names!)
|
||||
JsVar *jspParseFunctionAsArray(); ///< parse a function with any number of argument, and return an array of de-named aruments
|
||||
NO_INLINE int jspParseFunctionIntoArray(JsVar **array, int arraySize); ///< parse a function with any number of arguments into the given array, and return the size
|
||||
|
||||
/** Handle a function call (assumes we've parsed the function name and we're
|
||||
* on the start bracket). 'thisArg' is the value of the 'this' variable when the
|
||||
|
||||
10
src/jsvar.c
10
src/jsvar.c
@ -523,6 +523,16 @@ JsVar *jsvNewFromPin(int pin) {
|
||||
return v;
|
||||
}
|
||||
|
||||
/// Create an array containing the given elements
|
||||
JsVar *jsvNewArray(JsVar **elements, int elementCount) {
|
||||
JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
|
||||
if (!arr) return 0;
|
||||
int i;
|
||||
for (i=0;i<elementCount;i++)
|
||||
jsvArrayPush(arr, elements[i]);
|
||||
return arr;
|
||||
}
|
||||
|
||||
bool jsvIsBasicVarEqual(JsVar *a, JsVar *b) {
|
||||
// quick checks
|
||||
if (a==b) return true;
|
||||
|
||||
@ -156,6 +156,7 @@ JsVar *jsvNewFromFloat(JsVarFloat value);
|
||||
// Turns var into a Variable name that links to the given value... No locking so no need to unlock var
|
||||
JsVar *jsvMakeIntoVariableName(JsVar *var, JsVar *valueOrZero);
|
||||
JsVar *jsvNewFromPin(int pin);
|
||||
JsVar *jsvNewArray(JsVar **elements, int elementCount); ///< Create an array containing the given elements
|
||||
|
||||
/// DO NOT CALL THIS DIRECTLY - this frees an unreffed/locked var
|
||||
void jsvFreePtr(JsVar *var);
|
||||
|
||||
@ -15,6 +15,25 @@
|
||||
#include "jsutils.h"
|
||||
#include "jsparse.h"
|
||||
|
||||
typedef enum {
|
||||
JSWAT_FINISH = 0, // no argument
|
||||
JSWAT_VOID = 0, // Only for return values
|
||||
JSWAT_JSVAR, // standard variable
|
||||
JSWAT_JSVARNAME = JSWAT_JSVAR, // variable without the name being stripped off
|
||||
JSWAT_ARGUMENT_ARRAY, // a JsVar array containing all subsequent arguments
|
||||
JSWAT_BOOL, // boolean
|
||||
JSWAT_INT32, // 32 bit int
|
||||
JSWAT_PIN, // A pin
|
||||
JSWAT_JSVARINT, // 64 bit int
|
||||
JSWAT_JSVARFLOAT, // 64 bit float
|
||||
JSWAT__LAST = JSWAT_JSVARFLOAT,
|
||||
JSWAT_MASK = NEXT_POWER_2(JSWAT__LAST)-1
|
||||
} JsnArgumentType;
|
||||
|
||||
// number of bits needed for each argument bit
|
||||
#define JSWAT_BITS GET_BIT_NUMBER(JSWAT_MASK+1)
|
||||
|
||||
|
||||
#define JSW_HANDLEFUNCTIONCALL_UNHANDLED ((JsVar*)-1)
|
||||
|
||||
/** If 'name' is something that belongs to an internal function, execute it. */
|
||||
@ -43,3 +62,6 @@ void jswInit();
|
||||
|
||||
/** Tasks to run on Deinitialisation */
|
||||
void jswKill();
|
||||
|
||||
|
||||
JsVar *jswCallFunction(void *function, unsigned int argumentSpecifier, JsVar **paramData, int paramCount);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user