#!/usr/bin/env python import sys longNames = { "p": "void*", "i": "int", "l": "long", "h": "short", "L": "long long", "d": "double", "D": "long double", "s": "char*", # for the copying version "v": "void", "P": "void*", # or null "S": "char*", # or null "f": "float", "R": "Values::NodeT", # or null "V": "VARIANT", } def getLongName(c): return longNames[c] def checks2(combination): result = [combination] if combination.startswith("C") and len(combination) == 6: c = combination while len(c) > 2 and c[-1] == "i": c = c[:-1] result.append(c) return(result) def checks(combination): result = checks2(combination) extra = [] for entry in result: if entry[1] == "P": extra.append(entry[:1] + "p" + entry[2:]) return(result + extra) print(""" #include #include #include "TrampolineSymbols" #include <5D/Operations> #include <5D/FFIs> #include "Evaluators/FFI" #include "Evaluators/Builtins" #include "Numbers/Integer" #include "Numbers/Real" #include "FFIs/VariantPacker" namespace Trampolines { using namespace FFIs; static inline Values::NodeT extr(const Evaluators::CXXArguments::const_iterator& iter) { return(iter->second); } static inline void* getSomethingUseful(Values::NodeT n) { void* result = Values::pointerFromNode(n); if(result == NULL) throw Evaluators::EvaluationException("argument is required but empty"); return(result); } static inline void* getSomethingUsefulOrNull(Values::NodeT n) { if(n == NULL) return(NULL); else return(getSomethingUseful(n)); } static inline Values::NodeT makeStrOrNil(const char* s) { return(s ? Values::makeStr(s) : NULL); } static inline Values::NodeT makeBox(Values::NodeT repr, void* s) { if(s == NULL) throw Evaluators::EvaluationException("argument is required but empty"); return(Values::makeBox(s, repr)); } static inline Values::NodeT makeBoxOrNil(Values::NodeT repr, void* s) { return(s ? makeBox(repr, s) : NULL); } #ifdef WIN32 extern VARIANT variantEmpty; #endif #define unproc iter == end ? NULL : dynamic_cast(extr(iter++)) #define unp iter == end ? NULL : getSomethingUseful(extr(iter++)) #define unP iter == end ? NULL : getSomethingUsefulOrNull(extr(iter++)) #define uni iter == end ? 0 : Values::intFromNode(extr(iter++)) #define unl iter == end ? 0 : Values::longFromNode(extr(iter++)) #define unh iter == end ? 0 : Values::shortFromNode(extr(iter++)) #define unL iter == end ? 0 : Values::longLongFromNode(extr(iter++)) #define uns iter == end ? NULL : Values::stringFromNode(extr(iter++)) #define unS iter == end ? NULL : Values::stringFromNode(extr(iter++)) #define unf iter == end ? 0 : Values::floatFromNode(extr(iter++)) #define unD iter == end ? 0.0L : Values::longDoubleFromNode(extr(iter++)) #define und iter == end ? 0.0 : Values::doubleFromNode(extr(iter++)) #define unR iter == end ? NULL : extr(iter++) #define unV iter == end ? variantEmpty : FFIs::encodeVariantCXX(extr(iter++)) #define inv #define REPRME Values::makeApplication(options, world) #define inp makeBox(REPRME, #define inP makeBoxOrNil(REPRME, #define ini Numbers::internNative((Numbers::NativeInt) #define inl Numbers::internNative((Numbers::NativeInt) #define inh Numbers::internNative((Numbers::NativeInt) #define inL Numbers::internNative((long long) #define inf Numbers::internNative((Numbers::NativeFloat) #define inD Numbers::internNative((Numbers::NativeFloat) #define ind Numbers::internNative((Numbers::NativeFloat) #define ins Values::makeStr( #define inS makeStrOrNil( #define inR ( #define inV FFIs::decodeVariantCXX( /* FIXME do inL properly */ //typedef Values::NodeT (jumper_t)(Evaluators::CProcedure* p2, Evaluators::CXXArguments::const_iterator& iter, Evaluators::CXXArguments::const_iterator& end, Values::NodeT options, Values::NodeT world); static Hashtable fMarshallers; """) combinations = [] for combination in sys.stdin.readlines(): combination = combination.rstrip("\n") combinations.append(combination) def getReturner(): if combination[1] != "v": return ("result = in%s" % combination[1]) else: return "inv" def getCallingConvention(cc): if cc == "P": return "PASCAL" else: return "" def getFallback(): if combination[1] == "v": return "" else: return ")" def getInliner(combination): return("") content = combination[1 : ] print("typedef %s %s (*proc_%s_t)(%s);" % (getLongName(content[0]), getCallingConvention(combination[0]), combination, ", ".join(map(getLongName, content[1:])))) print("""static %(inliner)s Values::NodeT jump%(combination)s(Evaluators::CProcedure* p2, Evaluators::CXXArguments::const_iterator& iter, Evaluators::CXXArguments::const_iterator& end, Values::NodeT options, Values::NodeT world) { proc_%(combination)s_t proc = (proc_%(combination)s_t) p2->value; %(tempvariables)s Values::NodeT result = NULL; %(returner)s((*proc)(%(marshallers)s))%(fallback)s; return CHANGED_WORLD(result); }""" % { "combination": combination, "tempvariables": "\n ".join(map(lambda s: "%s a%d = un%s;" % (longNames[s[1]], s[0], s[1]), enumerate(combination[2:]))), "inliner": getInliner(combination), "marshallers": ", ".join(map(lambda s: "a%d" % s[0], enumerate(combination[2:]))), "returner": getReturner(), "fallback": getFallback(), }) print(""" #undef unP #undef unp #undef uni #undef unl #undef unh #undef unL #undef uns #undef unS #undef inP #undef inp #undef inP #undef ini #undef inl #undef inh #undef inL #undef ins #undef inS #undef inf #undef unf #undef unR #undef inR static void initMarshallers(void) { """) for combination in combinations: for check in checks(combination): #print(" fMarshallers[S_%(check)s->name] = jump%(check)s;" % { "check": check }) print(" fMarshallers[\"%(check)s\"] = jump%(combination)s;" % { "check": check, "combination": combination }) print(""" } /* end initMarshallers */ """) print(""" static Values::NodeT jumpT(Evaluators::CProcedure* proc, Values::NodeT options, Values::NodeT world) { Evaluators::CXXArguments arguments = Evaluators::CXXfromArguments(options, world); Evaluators::CXXArguments::const_iterator iter = arguments.begin(); Evaluators::CXXArguments::const_iterator endIter = arguments.end(); if(fMarshallers.empty()) initMarshallers(); assert(iter != endIter); assert(iter->first == NULL); --endIter; /* hide the world */ Hashtable::const_iterator iterMarshaller = fMarshallers.find(Values::get_symbol_name(proc->fSignature)/* TODO check NULL */); if(iterMarshaller == fMarshallers.end()) { return jumpFFI(proc, iter, endIter, options, world); } else return (*iterMarshaller->second)(proc, iter, endIter, options, world); } }; #undef unproc """)