/*- * Copyright (c) 2014-2017 Carsten Sonne Larsen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Project homepage: * http://amath.innolan.net * */ #include "math.h" #include "amath.h" #include "amathc.h" #include "nodes.h" #include "values.h" #include "lib/numb.h" #include "lib/real.h" #include "lib/cplex.h" #include "lib/charbuf.h" #include "localize/text.h" #include "system/program.h" // ----------------------------------------------------- // --------------------- Variable ---------------------- // ----------------------------------------------------- Variable::Variable(const char* name) { AllocAndCopy(&this->name, name); value = nullptr; Next = nullptr; chainDelete = true; } Variable::~Variable() { delete [] name; if (value != nullptr) { delete value; } if (chainDelete && Next != nullptr) { delete Next; } } char* Variable::GetName() const { return name; } Number* Variable::GetValue() const { return value->Clone();; } void Variable::AssignValue(Number* value) { if (this->value != nullptr) { delete this->value; } this->value = value->Clone(); } // ----------------------------------------------------- // ------------------- VariableList -------------------- // ----------------------------------------------------- VariableList::VariableList() { first = nullptr; buf = new CharBuffer(); } VariableList::~VariableList() { if (first != nullptr) { delete first; } delete buf; } void VariableList::Clear() { if (first != nullptr) { delete first; first = nullptr; } buf->ClearBuffer(); } bool VariableList::Delete(const char* name) { Variable* var = GetVariable(name); if (var == nullptr) { return false; } if (var == first) { first = var->Next; var->chainDelete = false; delete var; return true; } Variable* current = first->Next; Variable* last = first; while (current != var) { current = current->Next; last = last->Next; } last->Next = var->Next; // Only delete this variable. Not the whole chain. var->chainDelete = false; delete var; return true; } Variable* VariableList::GetFirstVariable() const { return first; } Variable* VariableList::GetVariable(const char* name) const { Variable* current = first; while (current != nullptr && !StrIsEqual(current->GetName(), name)) { current = current->Next; } return current; } Variable* VariableList::CreateVariable(const char* name) { if (first == nullptr) { first = new Variable(name); return first; } Variable* current = first; Variable* last = nullptr; while (current != nullptr) { if (StrIsEqual(name, current->GetName())) { return current; } last = current; current = current->Next; } current = new Variable(name); last->Next = current; return current; } Variable* VariableList::InsertTemporaryVariable(Variable* variable) { // Temporary variables are always inserted at the beginning of the list. Variable* oldFirst = first; first = variable; variable->Next = oldFirst; return variable; } void VariableList::RemoveTemporaryVariable() { // Temporary variables are not owned by the variable list. Do not free memory. Variable* newFirst = first->Next; first->Next = nullptr; first = newFirst; } char* VariableList::List() const { return ListContent(false); } char* VariableList::ListDefinitions() const { return ListContent(true); } char* VariableList::ListContent(bool cmdFormat) const { buf->Empty(); if (GetFirstVariable() == nullptr) { return static_cast(cmdFormat ? nullptr : HELPVARSNDEF); } int len = 0; Variable* current = GetFirstVariable(); while (current != nullptr) { len += StrLen(current->GetName()); len += 3; len += 32; // Max length of value len += cmdFormat ? 2 : 1; current = current->Next; } current = GetFirstVariable(); buf->EnsureSize(len); while (current != nullptr) { buf->Append(current->GetName()); buf->Append(" = "); Number* num = current->GetValue(); const char* val = Program->Output->GetText(num); buf->Append(val); delete num; if (cmdFormat) { buf->Append(';'); } buf->Append(NEWLINE); current = current->Next; } return buf->GetString(); } // ----------------------------------------------------- // -------------- ListVariablesStatement --------------- // ----------------------------------------------------- ListVariablesStatement::ListVariablesStatement() : StatementNode() { } char* ListVariablesStatement::Execute() { return Program->Variables->List(); } // ----------------------------------------------------- // ------------------- VariableNode -------------------- // ----------------------------------------------------- VariableNode::VariableNode(Variable* variable): ExpressionNode(), variable(variable) { } int VariableNode::GetPrecedence() { return 0; } Number* VariableNode::Evaluate() { result = variable->GetValue(); return result; } void VariableNode::AssignValue(Number* value) const { variable->AssignValue(value); } char* VariableNode::GetText() { return variable->GetName(); } char* VariableNode::GetNodeText() { return variable->GetName(); } SyntaxNode* VariableNode::GetNext() { return nullptr; } void VariableNode::Attach(SyntaxNode* node) { } void VariableNode::Detach(SyntaxNode* node) { } void VariableNode::Replace(SyntaxNode* n, SyntaxNode* x) { } // ----------------------------------------------------- // ----------------- InsVariableNode ------------------- // ----------------------------------------------------- InsVariableNode::InsVariableNode() : VariableNode(nullptr) { } Number* InsVariableNode::Evaluate() { return Program->GetLastResult(); } char* InsVariableNode::GetText() { static char* ret = (char*)"ins"; return ret; } char* InsVariableNode::GetNodeText() { static char* ret = (char*)"ins"; return ret; } // ----------------------------------------------------- // ----------------- NumericValueNode ------------------ // ----------------------------------------------------- NumericValueNode::NumericValueNode() : ExpressionNode(new RealNumber()) { } NumericValueNode::NumericValueNode(Number* value) : ExpressionNode(value) { } ReductionType NumericValueNode::GetReductionType() { return valuereduc; } int NumericValueNode::GetPrecedence() { return !leftBottom ? result->GetPrecedence() : result->GetDefaultPrecedence(); } Number* NumericValueNode::Evaluate() { return result; } char* NumericValueNode::GetText() { return GetNodeText(); } char* NumericValueNode::GetNodeText() { const char* val = Program->Input->GetText(result); output->ClearAndCopy(val); return output->GetString(); } SyntaxNode* NumericValueNode::GetNext() { return nullptr; } void NumericValueNode::Attach(SyntaxNode* node) { } void NumericValueNode::Detach(SyntaxNode* node) { } void NumericValueNode::Replace(SyntaxNode* n, SyntaxNode* x) { } void NumericValueNode::ReplaceWith(Number* value) { delete result; result = value; } // ----------------------------------------------------- // ----------------- EulersNumberNode ------------------ // ----------------------------------------------------- EulersNumberNode::EulersNumberNode() : NumericValueNode(new RealNumber(EULERS)) { } ReductionType EulersNumberNode::GetReductionType() { return nonereduc; } char* EulersNumberNode::GetNodeText() { static char* ret = (char*)"e"; return ret; } // ----------------------------------------------------- // ---------------------- PiNode ----------------------- // ----------------------------------------------------- PiNode::PiNode() : NumericValueNode(new RealNumber(PI)) { } ReductionType PiNode::GetReductionType() { return nonereduc; } char* PiNode::GetNodeText() { static char* ret = (char*)"pi"; return ret; } // ----------------------------------------------------- // ------------------- ComplexiNode -------------------- // ----------------------------------------------------- ComplexiNode::ComplexiNode() : NumericValueNode(new ComplexNumber(0.0, 1.0)) { } ReductionType ComplexiNode::GetReductionType() { return nonereduc; } char* ComplexiNode::GetNodeText() { static char* ret = (char*)"i"; return ret; }