void PythonEngineAgros::materialValues(const QString &function, double from, double to, QVector<double> *keys, QVector<double> *values, int count) { if (function.isEmpty()) return; // function bool succesfulRun = runExpression(function); if (!succesfulRun) { ErrorResult result = currentPythonEngineAgros()->parseError(); qDebug() << "Function: " << result.error(); } // prepare keys double step = (to - from) / (count - 1); QString keysVector = "["; for (int i = 0; i < count; i++) { double key = from + i * step; keys->append(key); if (i == 0) keysVector += QString("%1").arg(key + EPS_ZERO); else if (i == (count - 1)) keysVector += QString(", %1]").arg(key - EPS_ZERO); else keysVector += QString(", %1").arg(key); } // run expression runExpression(QString("agros2d_material_values = agros2d_material_eval(%1)").arg(keysVector)); // extract values PyObject *result = PyDict_GetItemString(m_dict, "agros2d_material_values"); if (result) { Py_INCREF(result); for (int i = 0; i < count; i++) values->append(PyFloat_AsDouble(PyList_GetItem(result, i))); Py_XDECREF(result); } // remove variables runExpression("del agros2d_material; del agros2d_material_values"); // error during execution if (keys->size() != values->size()) { keys->clear(); values->clear(); } }
bool PythonEngine::runExpressionConsole(const QString &expression) { bool successfulRun = runExpression(expression); emit executedScript(); return successfulRun; }
static bool runFunctionCall(ASTNode* node, MemoryStack* stack, Scope* scope, RuntimeError* error, Value* result) { assert(node->nodeType == AST_FUNCTION_CALL); bool stillWorking = true; // TODO: change this to temporary memory? Scope identifierScope = makeScope(nullptr); FunctionIdentifier identifier = {}; if (calcFunctionIdentifier(scope, &identifierScope, stack, error, node, &identifier)) { Function* funcToCall = getFunction(scope, identifier); if (funcToCall) { Scope functionScope = makeScope(scope); ListIterator<ASTNode> iterator = makeIterator(&node->functionCall.arguments); ListIterator<Argument> iterator2 = makeIterator(&funcToCall->identifier.arguments); while (stillWorking && hasNext(&iterator)) { ASTNode* node = getNext(&iterator); Argument* argFunctionRecieves = getNext(&iterator2); Variable* var = defineAVariable(argFunctionRecieves->identifier, argFunctionRecieves->type, stack, &functionScope); stillWorking = runExpression(node, stack, scope, error, &var->value); } if (stillWorking) { assert(!hasNext(&iterator) && !hasNext(&iterator2)); if (funcToCall->type == FT_INTERNAL) stillWorking = runStatement(funcToCall->body, stack, &functionScope, error); else funcToCall->func(funcToCall->identifier.name, &functionScope.variables, result); // TODO: externals error checking? } scopeFreeMemory(&functionScope, stack); } else { *error = RuntimeError{ RET_UNDEFINED_FUNCTION, identifier.name, node->functionCall.lineNumber }; stillWorking = false; } } else stillWorking = false; scopeFreeMemory(&identifierScope, stack); return stillWorking; }
static bool runStatement(ASTNode* node, MemoryStack* stack, Scope* scope, RuntimeError* error) { switch (node->nodeType) { case AST_STATEMENT_TYPE_DEFINITION: { if (getTypeDefinition(scope, node->typeDefinition.identifier, false)) { *error = RuntimeError{ RET_TYPE_ALREADY_DEFINED, node->typeDefinition.identifier, node->typeDefinition.lineNumber }; return false; } else { TypeDefinition* typeDef = scopePushToList(scope, stack, &scope->types); typeDef->identifier = node->typeDefinition.identifier; typeDef->members = {}; ListIterator<ASTNode> iterator = makeIterator(&node->typeDefinition.definitions); int currOffsetInBytes = 0; while (hasNext(&iterator)) { ASTNode* node = getNext(&iterator); StructMember* member = scopePushToList(scope, stack, &typeDef->members); member->identifier = node->variableDeclaration.identifier; member->type = makeType(scope, node->variableDeclaration.typeIdentifier); member->offsetInBytes = currOffsetInBytes; currOffsetInBytes += member->type.definition->totalSizeInBytes; } typeDef->totalSizeInBytes = currOffsetInBytes; return true; } } break; case AST_STATEMENT_VARIABLE_DECLARATION: { if (getVariable(scope, node->variableDeclaration.identifier, false)) { *error = RuntimeError{ RET_VARIABLE_ALREADY_DEFINED, node->variableDeclaration.identifier, node->variableDeclaration.lineNumber }; return false; } else { Variable* var = defineAVariable( node->variableDeclaration.identifier, makeType(scope, node->variableDeclaration.typeIdentifier), stack, scope); if (node->variableDeclaration.expression) return runExpression(node->variableDeclaration.expression, stack, scope, error, &var->value); else return true; // TODO: set default value } } break; case AST_STATEMENT_FUNCTION_DEFINITION: { Function func; func.type = FT_INTERNAL; func.identifier.name = node->functionDefinition.identifier; func.identifier.arguments = {}; bool stillWorking = true; if (!node->functionDefinition.returnType) func.returnType = Type{ nullptr, 0 }; else { func.returnType = makeType(scope, node->functionDefinition.returnType); if (!func.returnType.definition) { *error = RuntimeError{ RET_UNDEFINED_TYPE, node->functionDefinition.returnType->typeIdentifier.name, node->functionDefinition.lineNumber }; stillWorking = false; } } ListIterator<ASTNode> args = makeIterator(&node->functionDefinition.arguments); while (stillWorking && hasNext(&args)) { ASTNode* arg = getNext(&args); Argument* argument = scopePushToList(scope, stack, &func.identifier.arguments); argument->identifier = arg->variableDeclaration.identifier; argument->type = makeType(scope, arg->variableDeclaration.typeIdentifier); if (!argument->type.definition) { *error = RuntimeError{ RET_UNDEFINED_TYPE, arg->variableDeclaration.typeIdentifier->typeIdentifier.name, arg->variableDeclaration.lineNumber }; stillWorking = false; } } func.body = node->functionDefinition.body; Function* hasFunc = getFunction(scope, func.identifier, false); if (hasFunc) { *error = RuntimeError{ RET_FUNCTION_ALREADY_DEFINED, node->functionDefinition.identifier, node->functionDefinition.lineNumber }; stillWorking = false; } else { *scopePushToList(scope, stack, &scope->functions) = func; } return stillWorking; } break; case AST_STATEMENT_IF: { Scope ifScope = makeScope(scope); Value conditionResult = pushValue(&ifScope, stack, Type{ getTypeDefinition(scope, makeSlice("s32")), false }); bool stillWorking = runExpression(node->ifStatement.condition, stack, scope, error, &conditionResult); if (stillWorking) { if (*(int*)conditionResult.memory != 0) { stillWorking = runStatement(node->ifStatement.ifCase, stack, &ifScope, error); } else if (node->ifStatement.elseCase != nullptr) { stillWorking = runStatement(node->ifStatement.elseCase, stack, &ifScope, error); } } scopeFreeMemory(&ifScope, stack); return stillWorking; } break; case AST_STATEMENT_WHILE: { Scope whileScope = makeScope(scope); Value conditionResult = pushValue(&whileScope, stack, Type{ getTypeDefinition(scope, makeSlice("s32")), false }); bool stillWorking = runExpression(node->whileStatement.condition, stack, scope, error, &conditionResult); if (stillWorking) { while (*(int*)conditionResult.memory != 0) { if (!(stillWorking = runStatement(node->whileStatement.body, stack, &whileScope, error))) break; if (!(stillWorking = runExpression(node->whileStatement.condition, stack, scope, error, &conditionResult))) break; } } scopeFreeMemory(&whileScope, stack); return stillWorking; } break; case AST_STATEMENT_ASSIGNMENT: { Value value; if (getValue(scope, node->assignment.lValue, error, &value)) { return runExpression(node->assignment.expression, stack, scope, error, &value); } else return false; } break; case AST_STATEMENTS_BLOCK: { Scope blockScope = makeScope(scope); bool result = runStatements(&node->statementsBlock.statements, stack, &blockScope, error); scopeFreeMemory(&blockScope, stack); return result; } break; case AST_FUNCTION_CALL: { return runFunctionCall(node, stack, scope, error, nullptr); } break; default: { assert(!"this is not a statement!"); return false; } break; } }