Skip to content

Commit

Permalink
FExprs_Frame, FExpr_List and FExpr_Dict (#2579)
Browse files Browse the repository at this point in the history
Converted 
* Head_Frame -> FExpr_Frame
* Head_NamedList -> FExpr_Dict
* Head_List -> FExpr_List
  • Loading branch information
st-pasha authored Aug 19, 2020
1 parent a4096d1 commit ed7097d
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 297 deletions.
2 changes: 1 addition & 1 deletion src/core/expr/declarations.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ namespace expr {
Type,
Func,
List,
NamedList,
Dict,
Frame,
SliceAll,
SliceInt,
Expand Down
2 changes: 1 addition & 1 deletion src/core/expr/eval_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ py::oobj EvalContext::evaluate_delete() {
Kind jkind = jexpr_->get_expr_kind();
if (jkind == Kind::SliceAll) {
evaluate_delete_rows();
} else if (jkind == Kind::NamedList) {
} else if (jkind == Kind::Dict) {
throw TypeError() << "When del operator is applied, `j` selector cannot "
"be a dictionary";
}
Expand Down
79 changes: 1 addition & 78 deletions src/core/expr/expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
//------------------------------------------------------------------------------
#include "expr/expr.h"
#include "expr/head.h"
#include "expr/head_frame.h"
#include "expr/head_func.h"
#include "expr/head_list.h"
#include "expr/workframe.h"
#include "expr/eval_context.h"
#include "datatable.h"
Expand All @@ -39,47 +37,9 @@ namespace expr {
//------------------------------------------------------------------------------

OldExpr::OldExpr(py::robj src)
: FExpr()
{
if (src.is_dtexpr()) _init_from_dtexpr(src);
// else if (src.is_int()) _init_from_int(src);
// else if (src.is_string()) _init_from_string(src);
// else if (src.is_float()) _init_from_float(src);
// else if (src.is_bool()) _init_from_bool(src);
// else if (src.is_slice()) _init_from_slice(src);
else if (src.is_list_or_tuple()) _init_from_list(src);
else if (src.is_dict()) _init_from_dictionary(src);
// else if (src.is_anytype()) _init_from_type(src);
else if (src.is_generator()) _init_from_iterable(src);
// else if (src.is_none()) _init_from_none();
else if (src.is_frame()) _init_from_frame(src);
// else if (src.is_range()) _init_from_range(src);
else if (src.is_pandas_frame() ||
src.is_pandas_series()) _init_from_pandas(src);
else if (src.is_numpy_array() ||
src.is_numpy_marray()) _init_from_numpy(src);
// else if (src.is_ellipsis()) _init_from_ellipsis();
else {
throw TypeError() << "An object of type " << src.typeobj()
<< " cannot be used in an Expr";
}
}


void OldExpr::_init_from_dictionary(py::robj src) {
strvec names;
for (auto kv : src.to_pydict()) {
if (!kv.first.is_string()) {
throw TypeError() << "Keys in the dictionary must be strings";
}
names.push_back(kv.first.to_string());
inputs.emplace_back(as_fexpr(kv.second));
}
head = ptrHead(new Head_NamedList(std::move(names)));
}

xassert(src.is_dtexpr());

void OldExpr::_init_from_dtexpr(py::robj src) {
auto op = src.get_attr("_op").to_size_t();
auto args = src.get_attr("_args").to_otuple();
auto params = src.get_attr("_params").to_otuple();
Expand All @@ -92,43 +52,6 @@ void OldExpr::_init_from_dtexpr(py::robj src) {



void OldExpr::_init_from_frame(py::robj src) {
head = Head_Frame::from_datatable(src);
}


void OldExpr::_init_from_iterable(py::robj src) {
for (auto elem : src.to_oiter()) {
inputs.emplace_back(as_fexpr(elem));
}
head = ptrHead(new Head_List);
}


void OldExpr::_init_from_list(py::robj src) {
auto srclist = src.to_pylist();
size_t nelems = srclist.size();
for (size_t i = 0; i < nelems; ++i) {
inputs.emplace_back(as_fexpr(srclist[i]));
}
head = ptrHead(new Head_List);
}


void OldExpr::_init_from_numpy(py::robj src) {
head = Head_Frame::from_numpy(src);
}


void OldExpr::_init_from_pandas(py::robj src) {
head = Head_Frame::from_pandas(src);
}






//------------------------------------------------------------------------------
// Expr core functionality
//------------------------------------------------------------------------------
Expand Down
11 changes: 0 additions & 11 deletions src/core/expr/expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,6 @@ class OldExpr : public FExpr {
void prepare_by(EvalContext&, Workframe&, std::vector<SortFlag>&) const override;

std::shared_ptr<FExpr> unnegate_column() const override;

private:
// Construction helpers
void _init_from_dictionary(py::robj);
void _init_from_dtexpr(py::robj);
void _init_from_frame(py::robj);
void _init_from_iterable(py::robj);
void _init_from_list(py::robj);
void _init_from_numpy(py::robj);
void _init_from_pandas(py::robj);
void _init_from_type(py::robj);
};


Expand Down
19 changes: 10 additions & 9 deletions src/core/expr/fexpr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
// IN THE SOFTWARE.
//------------------------------------------------------------------------------
#include "expr/fexpr.h"
#include "expr/fexpr_dict.h"
#include "expr/fexpr_frame.h"
#include "expr/fexpr_list.h"
#include "expr/fexpr_literal.h"
#include "expr/expr.h" // OldExpr
#include "python/obj.h"
Expand Down Expand Up @@ -72,30 +75,28 @@ static ptrExpr extract_fexpr(py::robj src) {

ptrExpr as_fexpr(py::robj src) {
if (src.is_fexpr()) return extract_fexpr(src);
else if (src.is_dtexpr()) ;
else if (src.is_dtexpr()) return std::make_shared<OldExpr>(src);
else if (src.is_int()) return FExpr_Literal_Int::make(src);
else if (src.is_string()) return FExpr_Literal_String::make(src);
else if (src.is_float()) return FExpr_Literal_Float::make(src);
else if (src.is_bool()) return FExpr_Literal_Bool::make(src);
else if (src.is_slice()) return FExpr_Literal_Slice::make(src);
else if (src.is_list_or_tuple()) ;
else if (src.is_dict()) ;
else if (src.is_list_or_tuple()) return FExpr_List::make(src);
else if (src.is_dict()) return FExpr_Dict::make(src);
else if (src.is_anytype()) return FExpr_Literal_Type::make(src);
else if (src.is_generator()) ;
else if (src.is_generator()) return FExpr_List::make(src);
else if (src.is_none()) return FExpr_Literal_None::make();
else if (src.is_frame()) ;
else if (src.is_frame()) return FExpr_Frame::from_datatable(src);
else if (src.is_range()) return FExpr_Literal_Range::make(src);
else if (src.is_pandas_frame() ||
src.is_pandas_series()) ;
src.is_pandas_series()) return FExpr_Frame::from_pandas(src);
else if (src.is_numpy_array() ||
src.is_numpy_marray()) ;
src.is_numpy_marray()) return FExpr_Frame::from_numpy(src);
else if (src.is_ellipsis()) return ptrExpr(new FExpr_Literal_SliceAll());
else {
throw TypeError() << "An object of type " << src.typeobj()
<< " cannot be used in an FExpr";
}
// TODO: remove this
return std::make_shared<OldExpr>(src);
}


Expand Down
129 changes: 129 additions & 0 deletions src/core/expr/fexpr_dict.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
//------------------------------------------------------------------------------
// Copyright 2019-2020 H2O.ai
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//------------------------------------------------------------------------------
#include "expr/eval_context.h"
#include "expr/fexpr_dict.h"
#include "expr/workframe.h"
#include "utils/assert.h"
#include "utils/exceptions.h"
namespace dt {
namespace expr {


//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------

FExpr_Dict::FExpr_Dict(strvec&& names, vecExpr&& args)
: names_(std::move(names)),
args_(std::move(args))
{
xassert(names_.size() == args_.size());
}


ptrExpr FExpr_Dict::make(py::robj src) {
strvec names;
vecExpr args;
for (auto kv : src.to_pydict()) {
if (!kv.first.is_string()) {
throw TypeError() << "Keys in the dictionary must be strings";
}
names.push_back(kv.first.to_string());
args.emplace_back(as_fexpr(kv.second));
}
return ptrExpr(new FExpr_Dict(std::move(names), std::move(args)));
}




//------------------------------------------------------------------------------
// Evaluation
//------------------------------------------------------------------------------

Workframe FExpr_Dict::evaluate_n(EvalContext& ctx) const {
Workframe outputs(ctx);
for (size_t i = 0; i < args_.size(); ++i) {
Workframe arg_out = args_[i]->evaluate_n(ctx);
arg_out.rename(names_[i]);
outputs.cbind( std::move(arg_out) );
}
return outputs;
}


Workframe FExpr_Dict::evaluate_r(EvalContext& ctx, const sztvec&) const {
return evaluate_n(ctx);
}


Workframe FExpr_Dict::evaluate_f(EvalContext&, size_t) const {
throw TypeError() << "A dictionary cannot be used as an f-selector";
}


Workframe FExpr_Dict::evaluate_j(EvalContext& ctx) const {
return evaluate_n(ctx);
}


RowIndex FExpr_Dict::evaluate_i(EvalContext&) const {
throw TypeError() << "A dictionary cannot be used as an i-selector";
}


RiGb FExpr_Dict::evaluate_iby(EvalContext&) const {
throw TypeError() << "A dictionary cannot be used as an i-selector";
}




//------------------------------------------------------------------------------
// Misc
//------------------------------------------------------------------------------

Kind FExpr_Dict::get_expr_kind() const {
return Kind::Dict;
}


int FExpr_Dict::precedence() const noexcept {
return 17;
}


std::string FExpr_Dict::repr() const {
std::string out = "{";
for (size_t i = 0; i < names_.size(); ++i) {
if (i) out += ", ";
out += names_[i]; // TODO: escape if necessary
out += '=';
out += args_[i]->repr();
}
out += '}';
return out;
}



}} // namespace dt::expr
46 changes: 20 additions & 26 deletions src/core/expr/head_list.h → src/core/expr/fexpr_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,39 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//------------------------------------------------------------------------------
#ifndef dt_EXPR_HEAD_LIST_h
#define dt_EXPR_HEAD_LIST_h
#ifndef dt_EXPR_FEXPR_DICT_h
#define dt_EXPR_FEXPR_DICT_h
#include <string>
#include <vector>
#include "expr/head.h"
#include "expr/declarations.h"
#include "expr/fexpr.h"
namespace dt {
namespace expr {


class Head_List : public Head {
public:
Kind get_expr_kind() const override;
Workframe evaluate_n(const vecExpr&, EvalContext&) const override;
Workframe evaluate_j(const vecExpr&, EvalContext&) const override;
Workframe evaluate_r(const vecExpr&, EvalContext&, const sztvec&) const override;
Workframe evaluate_f(EvalContext&, size_t) const override;
RowIndex evaluate_i(const vecExpr&, EvalContext&) const override;
RiGb evaluate_iby(const vecExpr&, EvalContext&) const override;
void prepare_by(const vecExpr&, EvalContext&, Workframe&, std::vector<SortFlag>&) const override;
};



class Head_NamedList : public Head {
class FExpr_Dict : public FExpr {
private:
strvec names;
strvec names_;
vecExpr args_;

public:
Head_NamedList(strvec&&);
Kind get_expr_kind() const override;
Workframe evaluate_n(const vecExpr&, EvalContext&) const override;
Workframe evaluate_j(const vecExpr&, EvalContext&) const override;
Workframe evaluate_r(const vecExpr&, EvalContext&, const sztvec&) const override;
FExpr_Dict(strvec&&, vecExpr&&);
static ptrExpr make(py::robj);

Workframe evaluate_n(EvalContext&) const override;
Workframe evaluate_j(EvalContext&) const override;
Workframe evaluate_r(EvalContext&, const sztvec&) const override;
Workframe evaluate_f(EvalContext&, size_t) const override;
RowIndex evaluate_i(const vecExpr&, EvalContext&) const override;
RiGb evaluate_iby(const vecExpr&, EvalContext&) const override;
RowIndex evaluate_i(EvalContext&) const override;
RiGb evaluate_iby(EvalContext&) const override;

Kind get_expr_kind() const override;
int precedence() const noexcept override;
std::string repr() const override;
};




}} // namespace dt::expr
#endif
Loading

0 comments on commit ed7097d

Please sign in to comment.