/*
The usage of this source code file, including but not limited to the reading, the compilation and
redistribution, is subject to the license agreement detailed in the license.txt and license.pdf files
which accompany this source code. By proceeding to use this file you are acknowledging that you have
read either license.txt or license.pdf, and that you agree to be bound by the terms and conditions of
the license. If license.txt and license.pdf are not available, you are not licensed this file and you
must delete it permanently; or contact the author at proy@conceptualspeech.com to obtain a copy of
the license before proceeding to use this file.
Copyright Philippe Roy 2010 - proy@conceptualspeech.com.
*/
#pragma warning( disable : 4251 )
#include "v8.h"
#include <stack>
using namespace v8;
using std::stack;
#include "JSObjectSupport.h"
#include "Predicate.h"
#include "POSNode.h"
#include "DigitalConceptBuilder.h"
#include "StringUtils.h"
#include <Windows.h>
#include "DebugDefinitions.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
class POSNode;
Handle<ObjectTemplate> global;
JSTrace JSTrace::globTrace;
int g_alreadyReporting = 0;
stack<POSNode*> g_nodeContext;
stack<string> g_sourceContext;
#pragma warning( disable : 4290 )
Handle<ObjectTemplate> JSGetGlobal()
{
InitJavascriptGlobal();
return global;
}
Handle<Value> JSPrint(const Arguments& args)
{
String::AsciiValue ascii0(args[0]);
Handle<Value> result;
string dResultStr;
string dContent = *ascii0;
printf(dContent.c_str());
return result;
}
Handle<Value> JSAlert(const Arguments& args)
{
Handle<Value> result;
String::AsciiValue ascii0(args[0]);
String::AsciiValue ascii1((args.Length() > 1)?args[1]:args[0]);
string dCurSequence = DigitalConceptBuilder::GetCurSequence();
if ((args.Length() == 1) || (*ascii1 == dCurSequence))
{
MessageBox(NULL, *ascii0, "Javascript message", MB_OK);
}
return result;
}
Handle<Value> JSNewPredicate(const Arguments& args)
{
shared_auto_ptr<CPredicate> dReturn(new CPredicate());
dReturn->MemoryProtect();
return dReturn->CreateJavascriptInstance();
}
Handle<Value> JSSetResultPredicate(const Arguments& args)
{
Local<External> wrap = Local<External>::Cast(args[0]->ToObject()->GetInternalField(0));
shared_auto_ptr<CPredicate> usePredicate = static_cast<CPredicate*>(wrap->Value());
DigitalConceptBuilder::GetCurCalculationContext()->SetResultPredicate(usePredicate);
return NullValue();
}
Handle<Value> JSGetResultPredicate(const Arguments& args)
{
if (DigitalConceptBuilder::GetCurCalculationContext()->GetResultPredicate().get() != NULL)
{
return DigitalConceptBuilder::GetCurCalculationContext()->GetResultPredicate()->CreateJavascriptInstance();
}
else
{
return NullValue();
}
}
string ProcessValueToDisplay(Handle<Value> dValue, bool multiLine)
{
String::AsciiValue dReturnStr(dValue);
if ((string)*dReturnStr == "[object Predicate]")
{
Local<External> wrap1 = Local<External>::Cast(dValue->ToObject()->GetInternalField(0));
void* ptr1 = wrap1->Value();
CPredicate *dPredicate = (CPredicate*)ptr1;
string dPred = dPredicate->ToString(multiLine);
return dPred;
}
else if ((string)*dReturnStr == "[object POSNode]")
{
Local<External> wrap1 = Local<External>::Cast(dValue->ToObject()->GetInternalField(0));
void* ptr1 = wrap1->Value();
POSNode *dPOSNode = (POSNode*)ptr1;
if (dPOSNode != NULL)
{
string dPred = dPOSNode->GetNodeDesc() + ", " + dPOSNode->GetConstructionLine();
return dPred;
}
else
{
return "NULL";
}
}
else
{
string dContent = *dReturnStr;
return dContent;
}
}
Handle<Value> ExecuteJavascriptString(Persistent<Context> context, string dSourceStr, string nameStr, bool skiptrace, Handle<Script> *dScript) throw(CMathematicalError)
{
Context::Scope context_scope(context);
Handle<Value> result;
Handle<String> source = String::New(dSourceStr.c_str());
Handle<Script> script;
if (dScript == NULL)
{
Handle<Value> name = String::New(nameStr.c_str());
{
TryCatch try_catch;
script = Script::Compile(source, name);
if (script.IsEmpty())
{
String::AsciiValue error(try_catch.Exception());
string tmpString = *error;
CMathematicalError dError(tmpString);
throw(dError);
}
}
}
else
{
script = *dScript;
}
string indent = "";
if ((!skiptrace) && (DigitalConceptBuilder::GetCurCalculationContext()->GetJavascriptTrace()))
{
for (int i = 0; i < g_alreadyReporting; i++)
{
indent += "\t";
}
Handle<Value> dCurPredicate = ExecuteJavascriptString(context, "var curPredicate; curPredicate", "trace", true);
string dCurPredicateStr = ProcessValueToDisplay(dCurPredicate, false);
Handle<Value> dCurNode = ExecuteJavascriptString(context, "var curNode; curNode", "trace", true);
string dCurNodeStr = ProcessValueToDisplay(dCurNode, false);
printf("%s %s %s %s\n%s[\n", g_nodeContext.empty()?"":(indent + "NODE:" + g_nodeContext.top()->GetNodeDesc() + ((g_nodeContext.top()->GetConstructionLine() != "")?(", " + g_nodeContext.top()->GetConstructionLine()):"")).c_str(), g_sourceContext.empty()?"":(g_nodeContext.empty()?"":"\n" + indent + "REF:\"" + g_sourceContext.top() + "\"").c_str(), ("\n" + indent + "curPredicate: " + dCurPredicateStr).c_str(), ("\n" + indent + "curNode: " + dCurNodeStr).c_str(), indent.c_str());
SearchAndReplace(dSourceStr, "\n", "\1");
SearchAndReplace(dSourceStr, "\1", "\n\t" + indent);
SearchAndReplace(dSourceStr, "\r\n", "\1");
SearchAndReplace(dSourceStr, "\1", "\n");
printf("%s\t%s", indent.c_str(), dSourceStr.c_str());
printf("\n");
}
g_alreadyReporting++;
result = script->Run();
g_alreadyReporting--;
if ((!skiptrace) && (DigitalConceptBuilder::GetCurCalculationContext()->GetJavascriptTrace()))
{
string dDisplay = ProcessValueToDisplay(result, true);
SearchAndReplace(dDisplay, "\n", "\1");
SearchAndReplace(dDisplay, "\1", "\n" + indent);
Handle<Value> dCurPredicate = ExecuteJavascriptString(context, "var curPredicate; curPredicate", "trace", true);
string dCurPredicateStr = ProcessValueToDisplay(dCurPredicate, false);
printf("%s] -> %s, curPredicate -> %s\n\n", indent.c_str(), dDisplay.c_str(), dCurPredicateStr.c_str());
}
return result;
}
JSTrace::JSTrace(): m_enabled(false) {}
JSTrace::~JSTrace() {}
void JSTrace::SetEnable(bool value)
{
if ((!value) && (m_enabled) && (m_content.length() > 0))
{
printf(m_content.c_str());
m_content = "";
}
else if ((value) && (!m_enabled))
{
if (m_syntacticContext.length() > 0)
{
m_content += "Syntactic context: " + m_syntacticContext + "\n";
}
}
m_enabled = value;
}
void JSTrace::SetSyntacticContext(string dContext)
{
m_syntacticContext = dContext;
}
void JSTrace::AppendContext(string label, shared_auto_ptr<CPredicate> wp, shared_auto_ptr<POSNode> curNode)
{
if (m_enabled)
{
m_content += (label.length() > 0)?"Context: " + label + "\n":"";
if (wp.get() != NULL)
{
m_content += wp->Inspect(1);
}
if (curNode.get() != NULL)
{
m_content += curNode->Inspect(1);
}
}
}
Handle<Value> NullValue()
{
return Integer::New(0);
}
void InitJavascriptGlobal()
{
if (global.IsEmpty())
{
global = v8::ObjectTemplate::New();
global->Set(String::New("alert"), FunctionTemplate::New(JSAlert));
global->Set(String::New("print"), FunctionTemplate::New(JSPrint));
global->Set(String::New("new_predicate"), FunctionTemplate::New(JSNewPredicate));
global->Set(String::New("setResultPredicate"), FunctionTemplate::New(JSSetResultPredicate));
global->Set(String::New("getResultPredicate"), FunctionTemplate::New(JSGetResultPredicate));
}
}
#pragma warning( default : 4290 )