Example #1
0
void
CfgEmitter::selectFunctionCallees(const Function::Ptr &function) {
    // Use an iteration rather than a traversal because we want to consider all vertices that belong to the function, including
    // those not reachable from the entry vertex.
    BOOST_FOREACH (const ControlFlowGraph::VertexNode &vertex, graph_.vertices()) {
        if (vertexOrganization(vertex).isSelected() && owningFunction(vertex) == function) {
            BOOST_FOREACH (const ControlFlowGraph::EdgeNode &edge, vertex.outEdges()) {
                if (isInterFunctionEdge(edge)) {
                    if (!edgeOrganization(edge).isSelected()) {
                        edgeOrganization(edge).select();
                        edgeOrganization(edge).label(edgeLabel(edge));
                        edgeOrganization(edge).attributes(edgeAttributes(edge));
                    }
                    
                    Organization &tgt = vertexOrganization(edge.target());
                    if (!tgt.isSelected()) {
                        tgt.select();
                        Function::Ptr callee = owningFunction(edge.target());
                        if (callee && edge.target()->value().type() == V_BASIC_BLOCK &&
                            edge.target()->value().address() == callee->address()) {
                            // target is the entry block of a function
                            tgt.label(functionLabel(callee));
                            tgt.attributes(functionAttributes(callee));
                        } else {
                            // target is some block that isn't a function entry
                            tgt.label(vertexLabel(edge.target()));
                            tgt.attributes(vertexAttributes(edge.target()));
                        }
                    }
                }
            }
        }
    }
Example #2
0
void CCodeGenerator::operator()(Construct* expr) {
    // Look up the function by name in the current context.
    String::Ptr id = env_->name("@init");
    Class::Ptr clazz = expr->type()->clazz();
    Function::Ptr func = clazz->function(id);
    
    std::vector<Operand> args;
    for (Expression::Ptr a = expr->arguments(); a; a = a->next()) {
        args.push_back(emit(a));
    }

    return_ = alloc_temp(clazz->type());
    out_ << func->label() << "(";

    Formal::Ptr formal = func->formals();
    Expression::Ptr arg = expr->arguments();
    for (int i = 0; i < args.size(); i++) {
        if(!formal->is_self() && !formal->type()->equals(arg->type())) {
            // Cast to the appropriate C-type, since C doesn't know anything 
            // about subtypes, etc..
            out_ << "(";
            operator()(formal->type());
            out_ << ")";
        }
        out_ << args[i];
        if (i < args.size() - 1) {
            out_ << ", ";
        }
        formal = formal->next();
        arg = arg->next();
    }
    out_ << ");\n";
}
SAWYER_EXPORT std::string
Grammar::evalFunction(TokenStream &tokens, ErrorLocation &eloc) const {
    ASSERT_require(tokens.isa(TOK_FUNCTION));
    std::string funcName = tokens.lexeme();
    ASSERT_require(funcName.size() >= 2 && '@' == funcName[0]);
    funcName = funcName.substr(1);
    tokens.consume();

    // Get the function declaration
    const Function::Ptr func = functions_.getOrDefault(funcName);
    if (!func)
        throw SyntaxError("function \"" + funcName + "\" is not declared");

    // Parse the actual arguments
    std::vector<std::string> actuals;
    while (tokens.isa(TOK_LEFT)) {
        tokens.consume();
        if (func->isMacro()) {
            actuals.push_back(readArgument(tokens, eloc, CONSUME));
        } else {
            actuals.push_back(evalArgument(tokens, eloc, CONSUME));
        }
    }
    func->validateArgs(actuals, tokens);

    ErrorLocation::Trap t(eloc, tokens, "in function \"" + funcName + "\"");
    std::string retval = func->eval(*this, actuals);
    t.passed();
    return retval;
}
 bool operator()(const ControlFlowGraph &cfg, const ControlFlowGraph::ConstEdgeIterator &callEdge, size_t depth) {
     if (depth > partitioner.stackDeltaInterproceduralLimit())
         return false;
     ASSERT_require(callEdge != cfg.edges().end());
     ASSERT_require(callEdge->target()->value().type() == V_BASIC_BLOCK);
     Function::Ptr function = callEdge->target()->value().function();
     return function && !function->stackDelta().getOptional().orDefault();
 }
Example #5
0
static Value FunctionCall(const std::vector<Value>& args)
{
	if (args.size() < 1)
		BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for call()"));

	ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
	Function::Ptr self = static_cast<Function::Ptr>(vframe->Self);
	REQUIRE_NOT_NULL(self);

	std::vector<Value> uargs(args.begin() + 1, args.end());
	return self->InvokeThis(args[0], uargs);
}
Example #6
0
static Value FunctionCallV(const Value& thisArg, const Array::Ptr& args)
{
	ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
	Function::Ptr self = static_cast<Function::Ptr>(vframe->Self);
	REQUIRE_NOT_NULL(self);

	std::vector<Value> uargs;

	{
		ObjectLock olock(args);
		uargs = std::vector<Value>(args->Begin(), args->End());
	}

	return self->InvokeThis(thisArg, uargs);
}
Example #7
0
static void InvokeAttributeHandlerHelper(const Function::Ptr& callback,
    const Object::Ptr& object, const Value& cookie)
{
	std::vector<Value> arguments;
	arguments.push_back(object);
	callback->Invoke(arguments);
}
Example #8
0
static bool ArraySortCmp(const Function::Ptr& cmp, const Value& a, const Value& b)
{
	std::vector<Value> args;
	args.push_back(a);
	args.push_back(b);
	return cmp->Invoke(args);
}
Example #9
0
	static inline Value FunctionCall(ScriptFrame& frame, const Value& self, const Function::Ptr& func, const std::vector<Value>& arguments)
	{
		ScriptFrame vframe;
		
		if (!self.IsEmpty())
			vframe.Self = self;

		return func->Invoke(arguments);
	}
Example #10
0
ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
	Value self, vfunc;
	String index;

	if (m_FName->GetReference(frame, false, &self, &index))
		vfunc = VMOps::GetField(self, index, frame.Sandboxed, m_DebugInfo);
	else {
		ExpressionResult vfuncres = m_FName->Evaluate(frame);
		CHECK_RESULT(vfuncres);

		vfunc = vfuncres.GetValue();
	}

	if (vfunc.IsObjectType<Type>()) {
		std::vector<Value> arguments;
		for (Expression *arg : m_Args) {
			ExpressionResult argres = arg->Evaluate(frame);
			CHECK_RESULT(argres);

			arguments.push_back(argres.GetValue());
		}

		return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
	}

	if (!vfunc.IsObjectType<Function>())
		BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo));

	Function::Ptr func = vfunc;

	if (!func->IsSideEffectFree() && frame.Sandboxed)
		BOOST_THROW_EXCEPTION(ScriptError("Function is not marked as safe for sandbox mode.", m_DebugInfo));

	std::vector<Value> arguments;
	for (Expression *arg : m_Args) {
		ExpressionResult argres = arg->Evaluate(frame);
		CHECK_RESULT(argres);

		arguments.push_back(argres.GetValue());
	}

	return VMOps::FunctionCall(frame, self, func, arguments);
}
Example #11
0
static Array::Ptr ArrayMap(const Function::Ptr& function)
{
	ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
	Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);

	if (vframe->Sandboxed && !function->IsSideEffectFree())
		BOOST_THROW_EXCEPTION(ScriptError("Map function must be side-effect free."));

	Array::Ptr result = new Array();

	ObjectLock olock(self);
	for (const Value& item : self) {
		std::vector<Value> args;
		args.push_back(item);
		result->Add(function->Invoke(args));
	}

	return result;
}
Example #12
0
static Array::Ptr ArraySort(const std::vector<Value>& args)
{
	ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
	Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);

	Array::Ptr arr = self->ShallowClone();

	if (args.empty()) {
		ObjectLock olock(arr);
		std::sort(arr->Begin(), arr->End());
	} else {
		Function::Ptr function = args[0];

		if (vframe->Sandboxed && !function->IsSideEffectFree())
			BOOST_THROW_EXCEPTION(ScriptError("Sort function must be side-effect free."));

		ObjectLock olock(arr);
		std::sort(arr->Begin(), arr->End(), boost::bind(ArraySortCmp, args[0], _1, _2));
	}

	return arr;
}
Example #13
0
static Value ArrayReduce(const Function::Ptr& function)
{
	ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
	Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);

	if (vframe->Sandboxed && !function->IsSideEffectFree())
		BOOST_THROW_EXCEPTION(ScriptError("Reduce function must be side-effect free."));

	if (self->GetLength() == 0)
		return Empty;

	Value result = self->Get(0);

	ObjectLock olock(self);
	for (size_t i = 1; i < self->GetLength(); i++) {
		std::vector<Value> args;
		args.push_back(result);
		args.push_back(self->Get(i));
		result = function->Invoke(args);
	}

	return result;
}
Example #14
0
TEST(GTestFunction, TestInstanceOf) {
    Function::Ptr add = GTestFunctionAdd::create();
    ASSERT_TRUE(add->instanceof(Type<GTestFunctionAdd>::id()));
    ASSERT_TRUE(add->instanceof(Type<Function>::id()));
    ASSERT_TRUE(add->instanceof(Type<Mutable>::id()));
    ASSERT_TRUE(add->instanceof(Type<Object>::id()));

    ASSERT_FALSE(add->instanceof(Type<Immutable>::id()));
}
Example #15
0
void
CodeExpander::functor(Class* clazz) {
    // Generate the @call method for the functor, which contains a switch on
    // the type of the arugment passed to @call method.
    Function::Ptr func = clazz->function(env_->name("@call"));
    Location loc = clazz->location();
    String::Ptr fn = func->formals()->next()->name();
    IdentifierRef::Ptr guard(new IdentifierRef(loc, env_->name(""), fn));

    Expression::Ptr stmt;
    for (Feature::Ptr feat = clazz->features(); feat; feat = feat->next()) {
        if (Function* func = dynamic_cast<Function*>(feat.pointer())) {
            String* nm = func->name();
            if (nm->string().find("@case") == 0) {
                // This is a functor case, so generate a branch for it.  Each 
                // branch looks like this: self.@case_Type(obj)
                Type::Ptr type = func->formals()->next()->type();
                Expression::Ptr arg0(new IdentifierRef(loc, env_->name(""), env_->name("__self")));
                Expression::Ptr arg1(new Cast(loc, type, new IdentifierRef(loc, env_->name(""), fn)));
                arg0->type(func->formals()->type());
                arg1->type(func->formals()->next()->type());
                
                Expression::Ptr arg;
                arg = append(arg.pointer(), arg0.pointer());
                arg = append(arg.pointer(), arg1.pointer());
                IdentifierRef::Ptr id(new IdentifierRef(loc, env_->name(""), nm));
                Call::Ptr expr(new Call(loc, id, arg));
                expr->function(func);
                Is::Ptr is(new Is(loc, guard, type));
                stmt = new Conditional(loc, is, expr, stmt);
            }
        }
    }
    Block::Ptr block = new Block(loc, env_->string(""), stmt);
    func->block(block);  
    func->is_checked(false);
    semant_->operator()(func);
}
Example #16
0
static void InvokeAttributeHandlerHelper(const Function::Ptr& callback,
	const Object::Ptr& object, const Value& cookie)
{
	callback->Invoke({ object });
}
Example #17
0
TEST(GTestFunction, TestCall) {
    Function::Ptr add = GTestFunctionAdd::create();
    Function::Ptr addx2 = GTestFunctionAddx2::create();

    ASSERT_TRUE(add->call().instanceof(Type<Error>::id()));
    ASSERT_TRUE(add->call(1).equals(1));
    ASSERT_TRUE(add->call(1, 2).equals(3));
    ASSERT_TRUE(add->call(1, 2, 3).equals(6));
    ASSERT_TRUE(add->call(1, 2, 3, 4).equals(10));
    ASSERT_TRUE(add->call(1, 2, 3, 4, 5).equals(15));
    ASSERT_TRUE(add->call(1, 2, 3, 4, 5, 6).equals(21));
    ASSERT_TRUE(add->call(1, 2, 3, 4, 5, 6, 7).equals(28));
    ASSERT_TRUE(add->call(1, 2, 3, 4, 5, 6, 7, 8).equals(36));
    ASSERT_TRUE(add->call(1, 2, 3, 4, 5, 6, 7, 8, 9).equals(45));
    ASSERT_TRUE(addx2->call(1, 2, 3, 4, 5, 6, 7, 8, 9).equals(90));
}
Example #18
0
void Context::prepare(Function::Ptr function)
{
	throwOnError(_context->Prepare(function->function()));
}
Example #19
0
bool
sortFunctionsByAddress(const Function::Ptr &a, const Function::Ptr &b) {
    ASSERT_not_null(a);
    ASSERT_not_null(b);
    return a->address() < b->address();
}
Example #20
0
    Variant& StackMachine::evaluate(const VariableStore& store, const FunctionRegistry& functions)
    {
        reset();

        for(const auto& instruction : _instructions) {
            switch(instruction._opCode) {
                case NOP: {
                    break;
                }
                case PUSH: {
                    _valueStack.emplace(instruction._value);
                    break;
                }
                case PUSHVAR: {
                    if(instruction._value.getType() != INT) {
                        CSVSQLDB_THROW(StackMachineException, "expected an INT as variable index");
                    }

                    int64_t index = instruction._value.asInt();
                    _valueStack.emplace(store[static_cast<size_t>(index)]);
                    break;
                }
                case ADD:
                case SUB:
                case DIV:
                case MOD:
                case MUL:
                case EQ:
                case NEQ:
                case IS:
                case ISNOT:
                case GT:
                case GE:
                case LT:
                case LE:
                case AND:
                case OR:
                case CONCAT: {
                    const Variant lhs(getNextValue());
                    Variant& rhs(getTopValue());
                    rhs = binaryOperation(mapOpCodeToBinaryOperationType(instruction._opCode), lhs, rhs);
                    break;
                }
                case NOT: {
                    Variant& rhs(getTopValue());
                    rhs = unaryOperation(OP_NOT, BOOLEAN, rhs);
                    break;
                }
                case PLUS: {
                    // this is a nop, as the value will not change, so just leave it on the stack
                    break;
                }
                case MINUS: {
                    Variant& rhs = getTopValue();
                    rhs = unaryOperation(OP_MINUS, rhs.getType(), rhs);
                    break;
                }
                case BETWEEN: {
                    const Variant lhs = getNextValue();
                    const Variant from = getNextValue();
                    Variant& to = getTopValue();

                    Variant result(BOOLEAN);
                    if(not(lhs.isNull() || from.isNull() || to.isNull())) {
                        if(binaryOperation(OP_GE, to, from).asBool()) {
                            result = binaryOperation(OP_GE, lhs, from);
                            if(result.asBool()) {
                                result = binaryOperation(OP_LE, lhs, to);
                            }
                        } else {
                            result = binaryOperation(OP_GE, lhs, to);
                            if(result.asBool()) {
                                result = binaryOperation(OP_LE, lhs, from);
                            }
                        }
                    }
                    to = result;
                    break;
                }
                case FUNC: {
                    if(instruction._value.getType() != STRING) {
                        CSVSQLDB_THROW(StackMachineException, "expected a string as variable name");
                    }

                    std::string funcname = instruction._value.asString();
                    Function::Ptr func = functions.getFunction(funcname);
                    if(!func) {
                        CSVSQLDB_THROW(StackMachineException, "function '" << funcname << "' not found");
                    }
                    Variants parameter;
                    size_t count = func->getParameterTypes().size();
                    for(const auto& param : func->getParameterTypes()) {
                        Variant v = getNextValue();
                        if(param != v.getType()) {
                            try {
                                v = unaryOperation(OP_CAST, param, v);
                            } catch(const std::exception&) {
                                CSVSQLDB_THROW(StackMachineException,
                                               "calling function '" << funcname << "' with wrong parameter");
                            }
                        }
                        parameter.emplace(parameter.end(), v);
                        --count;
                    }
                    if(count) {
                        CSVSQLDB_THROW(StackMachineException, "too much parameters for function '" << funcname << "'");
                    }
                    _valueStack.emplace(func->call(parameter));
                    break;
                }
                case CAST: {
                    Variant& rhs = getTopValue();
                    rhs = unaryOperation(OP_CAST, instruction._value.getType(), rhs);
                    break;
                }
                case IN: {
                    size_t count = static_cast<size_t>(instruction._value.asInt());
                    const Variant lhs = getNextValue();
                    bool found(false);
                    for(size_t n = 0; n < count; ++n) {
                        Variant result = binaryOperation(OP_EQ, lhs, getNextValue());
                        if(result.asBool()) {
                            found = true;
                            ++n;
                            for(; n < count; ++n) {
                                // remove rest of the values from stack
                                _valueStack.pop();
                            }
                            break;
                        }
                    }
                    if(found) {
                        _valueStack.emplace(Variant(true));
                    } else {
                        _valueStack.emplace(Variant(false));
                    }
                    break;
                }
                case LIKE: {
                    if(!instruction._r) {
                        CSVSQLDB_THROW(StackMachineException, "expected a regexp in LIKE expression");
                    }
                    Variant lhs = getTopValue();
                    if(lhs.getType() != STRING) {
                        lhs = unaryOperation(OP_CAST, STRING, lhs);
                        CSVSQLDB_THROW(StackMachineException, "can only do like operations on strings");
                    }
                    if(instruction._r->match(lhs.asString())) {
                        _valueStack.emplace(Variant(true));
                    } else {
                        _valueStack.emplace(Variant(false));
                    }
                    break;
                }
            }
        }

        return _valueStack.top();
    }