amath/app/main/values.cpp

446 lines
9.4 KiB
C++

/*
* Copyright (c) 2015-2017 Carsten Sonne Larsen <cs@innolan.dk>
* 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.
*
*/
#include "clib.h"
#include "math.h"
#include "lib/numb.h"
#include "lib/real.h"
#include "lib/cplex.h"
#include "lib/charbuf.h"
#include "main/nodes.h"
#include "main/values.h"
#include "localize/text.h"
#include "system/program.h"
// -----------------------------------------------------
// --------------------- Variable ----------------------
// -----------------------------------------------------
Variable::Variable(const char *name)
{
AllocAndCopy(&this->name, name);
value = NOMEM;
Next = NOMEM;
chainDelete = true;
}
Variable::~Variable()
{
delete [] name;
if (value != NOMEM) {
delete value;
}
if (chainDelete && Next != NOMEM) {
delete Next;
}
}
char* Variable::GetName()
{
return name;
}
Number* Variable::GetValue()
{
return value->Clone();;
}
void Variable::AssignValue(Number *value)
{
if (this->value != NOMEM) {
delete this->value;
}
this->value = value->Clone();
}
// -----------------------------------------------------
// ------------------- VariableList --------------------
// -----------------------------------------------------
VariableList::VariableList()
{
first = NOMEM;
buf = new CharBuffer();
}
VariableList::~VariableList()
{
if (first != NOMEM) {
delete first;
}
delete buf;
}
void VariableList::Clear()
{
if (first != NOMEM) {
delete first;
first = NOMEM;
}
buf->ClearBuffer();
}
bool VariableList::Delete(const char *name)
{
Variable* var = GetVariable(name);
if (var == NOMEM) {
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()
{
return first;
}
Variable* VariableList::GetVariable(const char *name)
{
Variable* current = first;
while (current != NOMEM && !StrIsEqual(current->GetName(), name)) {
current = current->Next;
}
return current;
}
Variable* VariableList::CreateVariable(const char *name)
{
if (first == NOMEM) {
first = new Variable(name);
return first;
}
Variable* current = first;
Variable* last = NOMEM;
while (current != NOMEM) {
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 = NOMEM;
first = newFirst;
}
char* VariableList::List()
{
return ListContent(false);
}
char* VariableList::ListDefinitions()
{
return ListContent(true);
}
char* VariableList::ListContent(bool cmdFormat)
{
buf->Empty();
if (GetFirstVariable() == NOMEM) {
return (char*)(cmdFormat ? NOMEM : HELPVARSNDEF);
}
int len = 0;
Variable* current = GetFirstVariable();
while (current != NOMEM) {
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 != NOMEM) {
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)
{
variable->AssignValue(value);
}
char* VariableNode::GetText()
{
return variable->GetName();
}
char* VariableNode::GetNodeText()
{
return variable->GetName();
}
SyntaxNode* VariableNode::GetNext()
{
return NOMEM;
}
void VariableNode::Attach(SyntaxNode* node)
{ }
void VariableNode::Detach(SyntaxNode* node)
{ }
void VariableNode::Replace(SyntaxNode* n, SyntaxNode* x)
{ }
// -----------------------------------------------------
// ----------------- InsVariableNode -------------------
// -----------------------------------------------------
InsVariableNode::InsVariableNode() :
VariableNode(NOMEM)
{ }
Number* InsVariableNode::Evaluate()
{
return Program->GetLastResult();
}
char* InsVariableNode::GetText()
{
return (char*)"ins";
}
char* InsVariableNode::GetNodeText()
{
return (char*)"ins";
}
// -----------------------------------------------------
// ----------------- 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 NOMEM;
}
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()
{
return (char*)"e";
}
// -----------------------------------------------------
// ---------------------- PiNode -----------------------
// -----------------------------------------------------
PiNode::PiNode() :
NumericValueNode(new RealNumber(PI)) { }
ReductionType PiNode::GetReductionType()
{
return nonereduc;
}
char* PiNode::GetNodeText()
{
return (char*)"pi";
}
// -----------------------------------------------------
// ------------------- ComplexiNode --------------------
// -----------------------------------------------------
ComplexiNode::ComplexiNode() :
NumericValueNode(new ComplexNumber(0.0, 1.0)) { }
ReductionType ComplexiNode::GetReductionType()
{
return nonereduc;
}
char* ComplexiNode::GetNodeText()
{
return (char*)"i";
}