void ConstructorCallExpression::internalEval() const
{
    vector<void*> addresses;
    evaluateArguments(m_Arguments, addresses);
    m_pSubroutine->call(m_pReturnStorage, addresses.data());
    flush();
    /// (destruction after the call is context dependant => if stored in a const ref or an r-value reference, life time is longer and goes to the end of the scope, else its destroyed after current statement
}
void ConstructorCallExpression::internalEval( void* a_pDest ) const
{
    vector<void*> addresses;
    evaluateArguments(m_Arguments, addresses);
    m_pSubroutine->call(a_pDest, addresses.data());
}
c_exp c_exp::fromLispExp(lisp_exp exp, QHash<QString, DataType> dataTypes, QHash<QString, QString> wireNames) {
    if (exp.isLeaf()) {
        if (wireNames.contains(exp.value())) {
            DataType dt = dataTypes.value(exp.value());
            QString wireName = wireNames.value(exp.value());
            return c_exp(wireName, dt);
        } else {
            bool success;
            exp.value().toInt(&success);
            if (success) {
                return c_exp(exp.value(), DATATYPE_INT);
            } else {
                exp.value().toFloat(&success);
                if (success) {
                    return c_exp(exp.value(), DATATYPE_FLOAT);
                } else {
                    return c_exp(); // error condition
                }
            }
        }
    } else {
        QString theOperator = exp.element(0).value();
        if (theOperator == "+" || theOperator == "-") {
            QList<c_exp> results = evaluateArguments(exp, dataTypes, wireNames);
            DataType mostGeneralType = getMostGeneralType(results);
            DataType resultType;
            if (mostGeneralType.isAFP()) {
                resultType = DATATYPE_AFP(mostGeneralType.afpPrecision() - intLog2(results.size()));
            } else {
                resultType = mostGeneralType;
            }
            QList<QString> conversionCodes = getConversionCodes(results, resultType);
            QString code = conversionCodes.join(" " + theOperator + " ");
            return c_exp(code, resultType);
        } else if (theOperator == "*") {
            QList<c_exp > results = evaluateArguments(exp, dataTypes, wireNames);
            DataType mostGeneralType = getMostGeneralType(results);
            if (mostGeneralType.isAFP()) {
                QString lastCode = "(int64_t)(" + results[0].code() + ")";
                DataType lastType = results[0].type();
                for (int i = 1; i < results.size(); i++) {
                    c_exp result = results[i];
                    if (! result.isValid()) {
                        lastType = DataType();
                    }
                    lastCode = "(" + lastCode + ") * (" + result.code() + ")";
                    lastCode = "(" + lastCode + ") >> 32";
                    int lastAFPPrecision = lastType.isAFP() ? lastType.afpPrecision() : 0;
                    int resultAFPPrecision = result.type().isAFP() ? result.type().afpPrecision() : 0;
                    if (lastType.isValid()) {
                        lastType = DATATYPE_AFP(32 - ((32 - lastAFPPrecision) + (32 - resultAFPPrecision)));
                    }
                }
                lastCode = "(int)(" + lastCode + ")";
                return c_exp(lastCode, lastType);
            } else {
                DataType resultType = mostGeneralType;
                QList<QString> codes = getCodes(results);
                QString code = codes.join(" * ");
                return c_exp(code, resultType);
            }
        } else if (theOperator == "/") {
            return c_exp();
        } else if (theOperator == "//") {
            return c_exp();
        } else if (theOperator == "%") {
            return c_exp();
        } else if (theOperator == "mod") {
            return c_exp();
        } else if (theOperator == "if") {
            c_exp condResult = c_exp::fromLispExp(exp.element(1), dataTypes, wireNames);
            c_exp ifTrueResult = c_exp::fromLispExp(exp.element(2), dataTypes, wireNames);
            c_exp ifFalseResult = c_exp::fromLispExp(exp.element(3), dataTypes, wireNames);
            DataType resultType = moreGeneralType(ifTrueResult.type(), ifFalseResult.type());
            QString code = "(" + condResult.code() + ") ? (" + ifTrueResult.conversionTo(resultType).code() + ") : (" + ifFalseResult.conversionTo(resultType).code() + ")";
            return c_exp(code, resultType);
        } else if (theOperator == ">" || theOperator == "<" || theOperator == ">=" || theOperator == "<=" || theOperator == "==" || theOperator == "!=") {
            c_exp leftOperand = c_exp::fromLispExp(exp.element(1), dataTypes, wireNames);
            c_exp rightOperand = c_exp::fromLispExp(exp.element(2), dataTypes, wireNames);
            DataType resultType = moreGeneralType(leftOperand.type(), rightOperand.type());
            QString code = "(" + leftOperand.conversionTo(resultType).code() + ") " + theOperator + " (" + rightOperand.conversionTo(resultType).code() + ")";
            return c_exp(code, resultType);
        } else if (theOperator == "sqrt") {
            c_exp operand = c_exp::fromLispExp(exp.element(1), dataTypes, wireNames);
            QString code = "sqrt(" + operand.code() + ")";
            return c_exp(code, DATATYPE_FLOAT);
        } else if (theOperator == "read_adc") {
            QString code = "((int)read_adc(" + c_exp::fromLispExp(exp.element(1), dataTypes, wireNames).conversionTo(DATATYPE_INT).code() + ") << 16)";
            return c_exp(code, DATATYPE_AFP(27));
        } else {
            return c_exp(); // error condition
        }
    }
}