📄 nodes.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/nodes.cpp 5 2/14/03 4:20a Arm $
//-----------------------------------------------------------------------------
// Project: ShortHand interpreter
// Author: Andrei Remenchuk <andrei@remenchuk.com>
//-----------------------------------------------------------------------------
// nodes.cpp: implementations of ShortHand Syntax Tree nodes
///////////////////////////////////////////////////////////////////////////////
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "nodes.h"
#include "parser.h"
#include "shsql.h"
#include "utils.h"
#include "shorthand.h"
#include "yydef.h"
#include "value.h"
#include "module.h"
#include "sharray.h"
#include "hash.h"
#include "function.h"
#include "builtins.h"
ShhExpressionList* ShhExpressionList::null = new ShhExpressionList();
ShhVariable::ShhVariable(const char* name)
{
m_name = name;
m_initialized = false;
}
ShhVariable::~ShhVariable()
{
}
ShhVariable* ShhVariableList::find(const char* name)
{
for(int i=0,n=m_size; i<n; i++)
{
ShhVariable* var = get(i);
if (stricmp(var->getName(), name) == 0) return var;
}
return NULL;
}
/**
* Base object for all nodes in the graph
*/
ShhNode::ShhNode()
{
TRACE((22, "ShhNode(0x%08x )::ShhNode()\n", this));
//if (module == NULL) throw new ShhException("global module is not defined");
//m_location = yylloc;
m_index = -1;
m_content = NULL;
m_module = NULL;
}
ShhNode::ShhNode(const YYLTYPE& location) : m_location(location)
{
//if (module == NULL) throw new ShhException("global module is not defined");
m_index = -1;
//m_module = module;
m_content = NULL;
m_module = NULL;
}
void ShhNode::place(const YYLTYPE& location)
{
m_location = location;
}
ShhNode::~ShhNode()
{
TRACE((22, "ShhNode(0x%08x[%d])::~ShhNode()\n", this, m_index));
}
ShhException* ShhNode::mkexception(int code, const char* format, ...) const
{
va_list args; va_start(args, format);
string usertext; usertext.vprintf(format, args);
ShhException* ex = new ShhException
(
"\n<br>\n<b>%s</b>(%d:%d): %s\n<br>\n",
m_module->getName(), m_location.first_line, m_location.first_column,
usertext.cstr()
);
ex->setCode(code);
return ex;
}
ShhException* ShhNode::wrap(int code, ShhException* ex) const
{
if (ex->code() != 0) code = ex->code();
ShhException* newx = mkexception(code, "%s", ex->message());
delete ex;
return newx;
}
ShhObject* ShhNode::requireObjectValue(ShhValue& value)
{
if (!value.isObject())
throw mkexception(1052, "Expression doesn't evaluate as object");
return value.toObject();
}
ShhObject* ShhNode::requireObjectVariable(const char* name)
{
ShhVariable* v = m_module->findVariable(name);
if (v == NULL || !v->value().isObject())
throw mkexception(1009, "Variable '%s' doesn't have object value", name);
return v->value().toObject();
}
ShhValue& ShhExpression::lvalue()
{
throw mkexception(1080, "This expression cannot be assigned to");
}
ShhQualifier::ShhQualifier(const char* term)
{
m_items.add((char*)term);
m_fqname.append(term);
}
ShhQualifier* ShhQualifier::add(const char* term)
{
m_items.add((char*)term);
m_fqname.append(term);
return this;
}
// returns full-qualified name
const char* ShhQualifier::fqname()
{
return m_fqname;
}
void ShhExpressionList::evaluate(ShhValueList& results)
{
results.clear();
if (this != NULL)
{
for(int i=0,n=m_size; i<n; i++)
{
results.add(new ShhValue(get(i)->evaluate()));
}
}
}
ShhArithmetic::ShhArithmetic(int op, ShhExpression* left, ShhExpression* right)
{
m_operator = op;
m_left = left;
m_right = right;
}
ShhValue ShhArithmetic::evaluate()
{
ShhValue value1 = m_left->evaluate();
ShhValue value2 = m_right->evaluate();
switch(m_operator)
{
case '+': return value1 + value2; break;
case '-': return value1 - value2; break;
case '*': return value1 * value2; break;
case '/':
//if (value2.toInt() == 0) throw mkexception(1003, "division by zero");
return value1 / value2;
case '%':
if (value2.toInt() == 0) throw mkexception(1010, "modulus by zero");
return value1.toInt() % value2.toInt();
case MIN:
return (value1 < value2) ? value1 : value2;
case MAX:
return (value1 > value2) ? value1 : value2;
break;
default:
throw mkexception(1004, "unknown arithmetic operator: %d", m_operator);
}
}
ShhVariableRef::ShhVariableRef(const char* name)
: m_name(name)
{
}
ShhValue ShhVariableRef::evaluate()
{
return m_module->var(m_name)->value();
}
ShhValue& ShhVariableRef::lvalue()
{
return m_module->var(m_name)->value();
}
/*
ShhVariableLV::ShhVariableLV(const char* name)
: m_name(name)
{
}
ShhValue& ShhVariableLV::lvalue()
{
return m_module->var(m_name)->value();
}
*/
ShhPropertyRef::ShhPropertyRef(ShhExpression* object, const char* property_name)
{
m_object = object;
m_property_name = property_name;
}
ShhValue ShhPropertyRef::evaluate()
{
ShhValue o = m_object->evaluate();
if (!o.isObject())
throw mkexception(1038, "expression doesn't evaluate as object");
ShhObject* obj = o.toObject();
try
{
if (obj->hasMethod(m_property_name))
{
return obj->executeMethod(m_property_name, NULL);
}
}
catch(ShhObjectException* ex)
{
throw wrap(1011, ex);
}
try
{
return obj->getProperty(m_property_name);
} catch (ShhObjectException* ex) {
throw wrap(1002, ex);
}
}
ShhValue& ShhPropertyRef::lvalue()
{
ShhValue& o = m_object->lvalue();
if (!o.isObject())
throw mkexception(1038, "expression doesn't evaluate as object");
ShhObject* obj = o.toObject();
if (obj == NULL)
throw mkexception(1039, "object is NULL");
try
{
return obj->getProperty(m_property_name);
} catch (ShhObjectException* ex) {
throw wrap(1040, ex);
}
}
ShhValueMethodCall::ShhValueMethodCall(ShhExpression* object, const char* method_name, ShhExpressionList* args)
{
m_object = object;
m_method_name = method_name;
m_args = args;
}
ShhValue ShhValueMethodCall::evaluate()
{
ShhValue base = m_object->evaluate();
ShhObject* obj = requireObjectValue(base);
try
{
if (m_args == NULL || m_args->size() == 0)
return obj->executeMethod(m_method_name, NULL);
}
catch(ShhObjectException* ex)
{
throw wrap(1012, ex);
}
// evaluate arguments
ShhValueList args;
for(int i=0,n=m_args->size(); i<n; i++)
{
ShhValue value = m_args->get(i)->evaluate();
args.add(value.clone());
}
try
{
return obj->executeMethod(m_method_name, &args);
}
catch(ShhObjectException* ex)
{
throw wrap(1013, ex);
}
}
ShhConcat::ShhConcat(ShhExpression* left, ShhExpression* right)
{
m_left = left;
m_right = right;
}
ShhValue ShhConcat::evaluate()
{
string L, R;
m_left->evaluate().toString(L);
m_right->evaluate().toString(R);
int size = L.length() + R.length() + 1;
char* result = (char*) m_module->scratch().malloc( size );
memcpy(result, L, L.length());
memcpy(result + L.length(), R, R.length() + 1);
ShhValue v(result);
return v;
}
ShhFunctionCall::ShhFunctionCall(const char* function, ShhExpressionList* args)
{
m_function = function;
if (args != NULL)
m_args = args;
else
m_args = ShhExpressionList::null;
}
ShhValue ShhFunctionCall::evaluate()
{
// evaluate arguments
ShhValueList args;
if (m_args != NULL)
{
for(int i=0, n=m_args->size(); i<n; i++)
{
ShhValue arg = m_args->get(i)->evaluate();
args.add(arg.clone());
}
}
// execute function
try
{
return m_module->executeFunction(m_function, args);
}
catch(ShhObjectException* oex)
{
throw wrap(oex->code(), oex);
}
}
///////////////////////////////////////////////////////////////////
// PREDICATE NODES (BOOLEAN EXPRESSIONS)
///////////////////////////////////////////////////////////////////
ShhComparison::ShhComparison(int op, ShhExpression* left, ShhExpression* right)
{
m_operator = op;
m_left = left;
m_right = right;
}
bool ShhComparison::check()
{
ShhValue lv = m_left->evaluate();
ShhValue rv = m_right->evaluate();
switch(m_operator)
{
case '<': return lv < rv;
case '>': return lv > rv;
case '=': return lv == rv;
case NE: return lv != rv;
case LE: return lv <= rv;
case GE: return lv >= rv;
default:
throw mkexception(1015, "unknown boolean operator: %d", m_operator);
}
}
ShhBooleanArithmetic::ShhBooleanArithmetic(int op, ShhPredicate* left, ShhPredicate* right)
{
m_operation = op;
m_left = left;
m_right = right;
}
bool ShhBooleanArithmetic::check()
{
switch(m_operation)
{
case AND: return m_left->check() && m_right->check();
case OR: return m_left->check() || m_right->check();
case NOT: return !m_left->check();
default:
throw mkexception(1014, "unknown boolean connector: %d", m_operation);
}
}
///////////////////////////////////////////////////////////////////
// EXECUTABLE OPERATORS
///////////////////////////////////////////////////////////////////
ShhBatch::ShhBatch(ShhExecutable* first)
{
if (first != NULL) m_statements.add(first);
}
void ShhBatch::execute()
{
for(int i=0,n=m_statements.size(); i<n; i++)
{
m_statements.get(i)->execute();
}
}
ShhBatch* ShhBatch::add(ShhExecutable* statement)
{
if (statement != NULL) m_statements.add(statement);
return this;
}
ShhAssignment::ShhAssignment(ShhExpression* lvalue, ShhExpression* ex)
: m_lvalue(lvalue)
{
m_expression = ex;
}
void ShhAssignment::execute()
{
ShhValue& lvalue = m_lvalue->lvalue();
ShhValue rvalue = m_expression->evaluate();
lvalue = rvalue;
}
ShhObjectCtor::ShhObjectCtor(const char* type, ShhExpressionList* args)
: m_type(type)
{
m_args = args;
}
ShhValue ShhObjectCtor::evaluate()
{
ShhValueList params; m_args->evaluate(params);
try
{
ShhObject* object = m_module->createObject(m_type, m_location);
object->constructor(¶ms);
ShhValue tmp(object);
return tmp;
}
catch(ShhObjectException *oex)
{
throw ShhNode::wrap(1023, oex);
}
}
ShhPrint::ShhPrint(ShhExpression* ex, bool newline_after)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -