13 |
#include "../common/global_private.h" |
#include "../common/global_private.h" |
14 |
#include "../common/RTMath.h" |
#include "../common/RTMath.h" |
15 |
#include <assert.h> |
#include <assert.h> |
16 |
|
#include "CoreVMFunctions.h" // for VMIntResult, VMRealResult |
17 |
|
|
18 |
namespace LinuxSampler { |
namespace LinuxSampler { |
19 |
|
|
123 |
} |
} |
124 |
} |
} |
125 |
|
|
126 |
static String _unitToStr(Unit* unit) { |
static String _unitToStr(VMUnit* unit) { |
127 |
const StdUnit_t type = unit->unitType(); |
const StdUnit_t type = unit->unitType(); |
128 |
String sType; |
String sType; |
129 |
switch (type) { |
switch (type) { |
576 |
Unit( |
Unit( |
577 |
(fn) ? fn->returnUnitType(dynamic_cast<VMFnArgs*>(&*args)) : VM_NO_UNIT |
(fn) ? fn->returnUnitType(dynamic_cast<VMFnArgs*>(&*args)) : VM_NO_UNIT |
578 |
), |
), |
579 |
functionName(function), args(args), fn(fn), result(NULL) |
functionName(function), args(args), fn(fn), |
580 |
|
result( (fn) ? fn->allocResult(dynamic_cast<VMFnArgs*>(&*args)) : NULL ) |
581 |
{ |
{ |
582 |
} |
} |
583 |
|
|
584 |
|
FunctionCall::~FunctionCall() { |
585 |
|
if (result) { |
586 |
|
delete result; |
587 |
|
result = NULL; |
588 |
|
} |
589 |
|
} |
590 |
|
|
591 |
void FunctionCall::dump(int level) { |
void FunctionCall::dump(int level) { |
592 |
printIndents(level); |
printIndents(level); |
593 |
printf("FunctionCall '%s' args={\n", functionName.c_str()); |
printf("FunctionCall '%s' args={\n", functionName.c_str()); |
619 |
|
|
620 |
VMFnResult* FunctionCall::execVMFn() { |
VMFnResult* FunctionCall::execVMFn() { |
621 |
if (!fn) return NULL; |
if (!fn) return NULL; |
622 |
|
|
623 |
|
// tell function where it shall dump its return value to |
624 |
|
VMFnResult* oldRes = fn->boundResult(); |
625 |
|
fn->bindResult(result); |
626 |
|
|
627 |
// assuming here that all argument checks (amount and types) have been made |
// assuming here that all argument checks (amount and types) have been made |
628 |
// at parse time, to avoid time intensive checks on each function call |
// at parse time, to avoid time intensive checks on each function call |
629 |
return fn->exec(dynamic_cast<VMFnArgs*>(&*args)); |
VMFnResult* res = fn->exec(dynamic_cast<VMFnArgs*>(&*args)); |
630 |
|
|
631 |
|
// restore previous result binding of some potential toplevel or concurrent |
632 |
|
// caller, i.e. if exactly same function is called more than one time, |
633 |
|
// concurrently in a term by other FunctionCall objects, e.g.: |
634 |
|
// ~c := ceil( ceil(~a) + ~b) |
635 |
|
fn->bindResult(oldRes); |
636 |
|
|
637 |
|
if (!res) return res; |
638 |
|
|
639 |
|
VMExpr* expr = res->resultValue(); |
640 |
|
if (!expr) return res; |
641 |
|
|
642 |
|
// For performance reasons we always only let 'FunctionCall' assign the unit |
643 |
|
// type to the function's result expression, never by the function |
644 |
|
// implementation itself, nor by other classes, because a FunctionCall |
645 |
|
// object solely knows the unit type in O(1). |
646 |
|
ExprType_t type = expr->exprType(); |
647 |
|
if (type == INT_EXPR) { |
648 |
|
VMIntResult* intRes = dynamic_cast<VMIntResult*>(res); |
649 |
|
intRes->unitBaseType = unitType(); |
650 |
|
} else if (type == REAL_EXPR) { |
651 |
|
VMRealResult* realRes = dynamic_cast<VMRealResult*>(res); |
652 |
|
realRes->unitBaseType = unitType(); |
653 |
|
} |
654 |
|
|
655 |
|
return res; |
656 |
} |
} |
657 |
|
|
658 |
StmtFlags_t FunctionCall::exec() { |
StmtFlags_t FunctionCall::exec() { |
659 |
result = execVMFn(); |
VMFnResult* result = execVMFn(); |
660 |
if (!result) |
if (!result) |
661 |
return StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED); |
return StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED); |
662 |
return result->resultFlags(); |
return result->resultFlags(); |
663 |
} |
} |
664 |
|
|
665 |
vmint FunctionCall::evalInt() { |
vmint FunctionCall::evalInt() { |
666 |
result = execVMFn(); |
VMFnResult* result = execVMFn(); |
667 |
if (!result) return 0; |
if (!result) return 0; |
668 |
VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue()); |
VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue()); |
669 |
if (!intExpr) return 0; |
if (!intExpr) return 0; |
671 |
} |
} |
672 |
|
|
673 |
vmfloat FunctionCall::evalReal() { |
vmfloat FunctionCall::evalReal() { |
674 |
result = execVMFn(); |
VMFnResult* result = execVMFn(); |
675 |
if (!result) return 0; |
if (!result) return 0; |
676 |
VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue()); |
VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue()); |
677 |
if (!realExpr) return 0; |
if (!realExpr) return 0; |
679 |
} |
} |
680 |
|
|
681 |
VMIntArrayExpr* FunctionCall::asIntArray() const { |
VMIntArrayExpr* FunctionCall::asIntArray() const { |
682 |
|
//FIXME: asIntArray() not intended for evaluation semantics (for both |
683 |
|
// performance reasons with arrays, but also to prevent undesired value |
684 |
|
// mutation by implied (hidden) evaluation, as actually done here. We must |
685 |
|
// force function evaluation here though, because we need it for function |
686 |
|
// calls to be evaluated at all. This issue should be addressed cleanly by |
687 |
|
// adjusting the API appropriately. |
688 |
|
FunctionCall* rwSelf = const_cast<FunctionCall*>(this); |
689 |
|
VMFnResult* result = rwSelf->execVMFn(); |
690 |
|
|
691 |
if (!result) return 0; |
if (!result) return 0; |
692 |
VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue()); |
VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue()); |
693 |
return intArrExpr; |
return intArrExpr; |
694 |
} |
} |
695 |
|
|
696 |
VMRealArrayExpr* FunctionCall::asRealArray() const { |
VMRealArrayExpr* FunctionCall::asRealArray() const { |
697 |
|
//FIXME: asRealArray() not intended for evaluation semantics (for both |
698 |
|
// performance reasons with arrays, but also to prevent undesired value |
699 |
|
// mutation by implied (hidden) evaluation, as actually done here. We must |
700 |
|
// force function evaluation here though, because we need it for function |
701 |
|
// calls to be evaluated at all. This issue should be addressed cleanly by |
702 |
|
// adjusting the API appropriately. |
703 |
|
FunctionCall* rwSelf = const_cast<FunctionCall*>(this); |
704 |
|
VMFnResult* result = rwSelf->execVMFn(); |
705 |
|
|
706 |
if (!result) return 0; |
if (!result) return 0; |
707 |
VMRealArrayExpr* realArrExpr = dynamic_cast<VMRealArrayExpr*>(result->resultValue()); |
VMRealArrayExpr* realArrExpr = dynamic_cast<VMRealArrayExpr*>(result->resultValue()); |
708 |
return realArrExpr; |
return realArrExpr; |
709 |
} |
} |
710 |
|
|
711 |
String FunctionCall::evalStr() { |
String FunctionCall::evalStr() { |
712 |
result = execVMFn(); |
VMFnResult* result = execVMFn(); |
713 |
if (!result) return ""; |
if (!result) return ""; |
714 |
VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue()); |
VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue()); |
715 |
if (!strExpr) return ""; |
if (!strExpr) return ""; |
717 |
} |
} |
718 |
|
|
719 |
String FunctionCall::evalCastToStr() { |
String FunctionCall::evalCastToStr() { |
720 |
result = execVMFn(); |
VMFnResult* result = execVMFn(); |
721 |
if (!result) return ""; |
if (!result) return ""; |
722 |
const ExprType_t resultType = result->resultValue()->exprType(); |
const ExprType_t resultType = result->resultValue()->exprType(); |
723 |
if (resultType == STRING_EXPR) { |
if (resultType == STRING_EXPR) { |
725 |
return strExpr ? strExpr->evalStr() : ""; |
return strExpr ? strExpr->evalStr() : ""; |
726 |
} else if (resultType == REAL_EXPR) { |
} else if (resultType == REAL_EXPR) { |
727 |
VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue()); |
VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue()); |
728 |
return realExpr ? ToString(realExpr->evalReal()) : ""; |
return realExpr ? ToString(realExpr->evalReal()) + _unitToStr(realExpr) : ""; |
729 |
} else { |
} else { |
730 |
VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue()); |
VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue()); |
731 |
return intExpr ? ToString(intExpr->evalInt()) : ""; |
return intExpr ? ToString(intExpr->evalInt()) + _unitToStr(intExpr) : ""; |
732 |
} |
} |
733 |
} |
} |
734 |
|
|
1852 |
} |
} |
1853 |
} |
} |
1854 |
|
|
1855 |
void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { |
void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, |
1856 |
|
int lastColumn, int firstByte, int lengthBytes, |
1857 |
|
const char* txt) |
1858 |
|
{ |
1859 |
ParserIssue e; |
ParserIssue e; |
1860 |
e.type = PARSER_ERROR; |
e.type = PARSER_ERROR; |
1861 |
e.txt = txt; |
e.txt = txt; |
1863 |
e.lastLine = lastLine; |
e.lastLine = lastLine; |
1864 |
e.firstColumn = firstColumn; |
e.firstColumn = firstColumn; |
1865 |
e.lastColumn = lastColumn; |
e.lastColumn = lastColumn; |
1866 |
|
e.firstByte = firstByte; |
1867 |
|
e.lengthBytes = lengthBytes; |
1868 |
vErrors.push_back(e); |
vErrors.push_back(e); |
1869 |
vIssues.push_back(e); |
vIssues.push_back(e); |
1870 |
} |
} |
1871 |
|
|
1872 |
void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { |
void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, |
1873 |
|
int lastColumn, int firstByte, int lengthBytes, |
1874 |
|
const char* txt) |
1875 |
|
{ |
1876 |
ParserIssue w; |
ParserIssue w; |
1877 |
w.type = PARSER_WARNING; |
w.type = PARSER_WARNING; |
1878 |
w.txt = txt; |
w.txt = txt; |
1880 |
w.lastLine = lastLine; |
w.lastLine = lastLine; |
1881 |
w.firstColumn = firstColumn; |
w.firstColumn = firstColumn; |
1882 |
w.lastColumn = lastColumn; |
w.lastColumn = lastColumn; |
1883 |
|
w.firstByte = firstByte; |
1884 |
|
w.lengthBytes = lengthBytes; |
1885 |
vWarnings.push_back(w); |
vWarnings.push_back(w); |
1886 |
vIssues.push_back(w); |
vIssues.push_back(w); |
1887 |
} |
} |
1888 |
|
|
1889 |
void ParserContext::addPreprocessorComment(int firstLine, int lastLine, int firstColumn, int lastColumn) { |
void ParserContext::addPreprocessorComment(int firstLine, int lastLine, |
1890 |
|
int firstColumn, int lastColumn, |
1891 |
|
int firstByte, int lengthBytes) |
1892 |
|
{ |
1893 |
CodeBlock block; |
CodeBlock block; |
1894 |
block.firstLine = firstLine; |
block.firstLine = firstLine; |
1895 |
block.lastLine = lastLine; |
block.lastLine = lastLine; |
1896 |
block.firstColumn = firstColumn; |
block.firstColumn = firstColumn; |
1897 |
block.lastColumn = lastColumn; |
block.lastColumn = lastColumn; |
1898 |
|
block.firstByte = firstByte; |
1899 |
|
block.lengthBytes = lengthBytes; |
1900 |
vPreprocessorComments.push_back(block); |
vPreprocessorComments.push_back(block); |
1901 |
} |
} |
1902 |
|
|