Skip to content

Commit

Permalink
Add performance improvements [WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed May 18, 2015
1 parent a9f2ca6 commit dd7e37e
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 60 deletions.
28 changes: 11 additions & 17 deletions ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,17 +641,17 @@ namespace Sass {

string Number::unit() const
{
stringstream u;
string u;
for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
if (i) u << '*';
u << numerator_units_[i];
if (i) u += '*';
u += numerator_units_[i];
}
if (!denominator_units_.empty()) u << '/';
if (!denominator_units_.empty()) u += '/';
for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
if (i) u << '*';
u << denominator_units_[i];
if (i) u += '*';
u += denominator_units_[i];
}
return u.str();
return u;
}

bool Number::is_unitless()
Expand Down Expand Up @@ -842,17 +842,11 @@ namespace Sass {

bool Number::operator== (Expression* rhs) const
{
try
{
Number l(pstate_, value_, unit());
Number& r = dynamic_cast<Number&>(*rhs);
l.normalize(find_convertible_unit());
r.normalize(find_convertible_unit());
return l.unit() == r.unit() &&
l.value() == r.value();
if (Number* r = static_cast<Number*>(rhs)) {
return (value() == r->value()) &&
(numerator_units_ == r->numerator_units_) &&
(denominator_units_ == r->denominator_units_);
}
catch (std::bad_cast&) {}
catch (...) { throw; }
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ namespace Sass {
0, 0
);
import_stack.push_back(import);
Parser p(Parser::from_c_str(queue[i].source, *this, ParserState(queue[i].abs_path, queue[i].source, i)));
Parser p(Parser::from_c_str(queue[i].source, *this, ParserState(queue[i].abs_path.c_str(), queue[i].source, i)));
Block* ast = p.parse();
sass_delete_import(import_stack.back());
import_stack.pop_back();
Expand Down
35 changes: 25 additions & 10 deletions environment.hpp
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
#ifndef SASS_ENVIRONMENT_H
#define SASS_ENVIRONMENT_H

#include <map>
#include <string>
#include <iostream>
#include <unordered_map>

#include "ast_fwd_decl.hpp"
#include "ast_def_macros.hpp"
#include "memory_manager.hpp"

namespace Sass {
using std::string;
using std::map;
using std::unordered_map;
using std::cerr;
using std::endl;

template <typename T>
class Environment {
// TODO: test with unordered_map
map<string, T> local_frame_;
unordered_map<string, T> local_frame_;
ADD_PROPERTY(Environment*, parent);

public:
Memory_Manager<AST_Node> mem;
Environment() : local_frame_(map<string, T>()), parent_(0) { }
Environment(Environment* env) : local_frame_(map<string, T>()), parent_(env) { }
Environment(Environment& env) : local_frame_(map<string, T>()), parent_(&env) { }
Environment() : local_frame_(unordered_map<string, T>()), parent_(0) { }
Environment(Environment* env) : local_frame_(unordered_map<string, T>()), parent_(env) { }
Environment(Environment& env) : local_frame_(unordered_map<string, T>()), parent_(&env) { }

// link parent to create a stack
void link(Environment& env) { parent_ = &env; }
Expand All @@ -42,19 +42,19 @@ namespace Sass {
// there is still a parent around
// not sure what it is actually use for
// I guess we store functions etc. there
bool is_root_scope() const
bool is_global() const
{
return parent_ && ! parent_->parent_;
}

// scope operates on the current frame

map<string, T>& local_frame() {
unordered_map<string, T>& local_frame() {
return local_frame_;
}

bool has_local(const string& key) const
{ return local_frame_.count(key) != 0; }
{ return local_frame_.find(key) != local_frame_.end(); }

T& get_local(const string& key)
{ return local_frame_[key]; }
Expand Down Expand Up @@ -119,6 +119,21 @@ namespace Sass {
set_local(key, val);
}

// see if we have a lexical we could update
// either update already existing lexical value
// or if flag is set, we create one if no lexical found
T& get_lexical(const string& key)
{
auto cur = this;
while (cur) {
if (cur->has_local(key)) {
return cur->get_local(key);
}
cur = cur->parent_;
}
return get_local(key);
}

// look on the full stack for key
// include all scopes available
bool has(const string& key) const
Expand Down Expand Up @@ -149,7 +164,7 @@ namespace Sass {
#ifdef DEBUG
void print()
{
for (typename map<string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
for (typename unordered_map<string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
cerr << i->first << endl;
}
if (parent_) {
Expand Down
30 changes: 20 additions & 10 deletions eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ namespace Sass {
// if one of the operands is a '/' then make sure it's evaluated
Expression* lhs = b->left()->perform(this);
lhs->is_delayed(false);

while (typeid(*lhs) == typeid(Binary_Expression)) lhs = lhs->perform(this);

switch (op_type) {
Expand Down Expand Up @@ -478,8 +479,8 @@ namespace Sass {
}
else
{
rhs->is_delayed(false);
rhs = rhs->perform(this);
// rhs->set_delayed(false);
// rhs = rhs->perform(this);
}

// see if it's a relational expression
Expand Down Expand Up @@ -797,12 +798,18 @@ namespace Sass {

Expression* Eval::operator()(Number* n)
{
n->normalize();
// behave according to as ruby sass (add leading zero)
return new (ctx.mem) Number(n->pstate(),
n->value(),
n->unit(),
true);
return n;
// we may not even need a copy after all
// we do not copy string constants either
/*
if (n->is_expanded()) return n;
Number* nn = new (ctx.mem) Number(n->pstate(),
n->value(),
n->unit(),
true);
nn->is_expanded(true);
return nn;
*/
}

Expression* Eval::operator()(Boolean* b)
Expand Down Expand Up @@ -1056,8 +1063,11 @@ namespace Sass {
} break;

case Expression::NUMBER: {
return *static_cast<Number*>(lhs) ==
*static_cast<Number*>(rhs);
Number* l = static_cast<Number*>(lhs);
Number* r = static_cast<Number*>(rhs);
return (l->value() == r->value()) &&
(l->numerator_units() == r->numerator_units()) &&
(l->denominator_units() == r->denominator_units());
} break;

case Expression::COLOR: {
Expand Down
1 change: 1 addition & 0 deletions expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Sass {
Expand::Expand(Context& ctx, Env* env, Backtrace* bt)
: ctx(ctx),
eval(Eval(*this)),
com_stack(vector<Env>()),
env_stack(vector<Env*>()),
block_stack(vector<Block*>()),
property_stack(vector<String*>()),
Expand Down
1 change: 1 addition & 0 deletions expand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace Sass {
Eval eval;

// it's easier to work with vectors
vector<Env> com_stack;
vector<Env*> env_stack;
vector<Block*> block_stack;
vector<String*> property_stack;
Expand Down
3 changes: 2 additions & 1 deletion functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,8 @@ namespace Sass {
{
List* l = dynamic_cast<List*>(env["$list"]);
Expression* v = ARG("$val", Expression);
String_Constant* sep = ARG("$separator", String_Constant);
// return v;
String_Constant* sep = ARG("$separator", String_Constant);
if (!l) {
l = new (ctx.mem) List(pstate, 1);
*l << ARG("$list", Expression);
Expand Down
59 changes: 51 additions & 8 deletions lexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,26 +142,69 @@ namespace Sass {
// Tries supplied matchers in order.
// Succeeds if one of them succeeds.
// Regex equivalent: /(?:FOO|BAR)/
template <prelexer... mxs>
template <const prelexer mx>
const char* alternatives(const char* src) {
const char* rslt;
for (prelexer mx : { mxs... }) {
if ((rslt = mx(src))) return rslt;
}
if ((rslt = mx(src))) return rslt;
return 0;
}
template <const prelexer mx1, const prelexer mx2>
const char* alternatives(const char* src) {
const char* rslt;
if ((rslt = mx1(src))) return rslt;
if ((rslt = mx2(src))) return rslt;
return 0;
}
template <const prelexer mx1, const prelexer mx2, const prelexer mx3>
const char* alternatives(const char* src) {
const char* rslt;
if ((rslt = mx1(src))) return rslt;
if ((rslt = mx2(src))) return rslt;
if ((rslt = mx3(src))) return rslt;
return 0;
}
template <const prelexer mx1, const prelexer mx2, const prelexer mx3, const prelexer mx4, const prelexer... mxs>
const char* alternatives(const char* src) {
const char* rslt;
if ((rslt = mx1(src))) return rslt;
if ((rslt = mx2(src))) return rslt;
if ((rslt = mx3(src))) return rslt;
return alternatives<mx4, mxs...>(src);
}

// Tries supplied matchers in order.
// Succeeds if all of them succeeds.
// Regex equivalent: /(?:FOO)(?:BAR)/
template <prelexer... mxs>
template <const prelexer mx1>
const char* sequence(const char* src) {
const char* rslt = src;
for (prelexer mx : { mxs... }) {
if (!(rslt = mx(rslt))) return 0;
}
if (!(rslt = mx1(rslt))) return 0;
return rslt;
}
template <const prelexer mx1, const prelexer mx2>
const char* sequence(const char* src) {
const char* rslt = src;
if (!(rslt = mx1(rslt))) return 0;
if (!(rslt = mx2(rslt))) return 0;
return rslt;
}
template <const prelexer mx1, const prelexer mx2, const prelexer mx3>
const char* sequence(const char* src) {
const char* rslt = src;
if (!(rslt = mx1(rslt))) return 0;
if (!(rslt = mx2(rslt))) return 0;
if (!(rslt = mx3(rslt))) return 0;
return rslt;
}
template <const prelexer mx1, const prelexer mx2, const prelexer mx3, const prelexer mx4, const prelexer... mxs>
const char* sequence(const char* src) {
const char* rslt = src;
if (!(rslt = mx1(rslt))) return 0;
if (!(rslt = mx2(rslt))) return 0;
if (!(rslt = mx3(rslt))) return 0;
return sequence<mx4, mxs...>(rslt);
}


// Match a pattern or not. Always succeeds.
// Regex equivalent: /(?:literal)?/
Expand Down
6 changes: 3 additions & 3 deletions position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ namespace Sass {
: Offset(line, column), file(file) { }


ParserState::ParserState(string path, const char* src, const size_t file)
ParserState::ParserState(const char* path, const char* src, const size_t file)
: Position(file, 0, 0), path(path), src(src), offset(0, 0), token() { }

ParserState::ParserState(string path, const char* src, Position position, Offset offset)
ParserState::ParserState(const char* path, const char* src, const Position& position, Offset offset)
: Position(position), path(path), src(src), offset(offset), token() { }

ParserState::ParserState(string path, const char* src, Token token, Position position, Offset offset)
ParserState::ParserState(const char* path, const char* src, const Token& token, const Position& position, Offset offset)
: Position(position), path(path), src(src), offset(offset), token(token) { }

Position Position::add(const char* begin, const char* end)
Expand Down
8 changes: 4 additions & 4 deletions position.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,17 @@ namespace Sass {
class ParserState : public Position {

public: // c-tor
ParserState(string path, const char* src = 0, const size_t file = string::npos);
ParserState(string path, const char* src, Position position, Offset offset = Offset(0, 0));
ParserState(string path, const char* src, Token token, Position position, Offset offset = Offset(0, 0));
ParserState(const char* path, const char* src = 0, const size_t file = string::npos);
ParserState(const char* path, const char* src, const Position& position, Offset offset = Offset(0, 0));
ParserState(const char* path, const char* src, const Token& token, const Position& position, Offset offset = Offset(0, 0));

public: // down casts
Offset off() { return *this; };
Position pos() { return *this; };
ParserState pstate() { return *this; };

public:
string path;
const char* path;
const char* src;
Offset offset;
Token token;
Expand Down
4 changes: 0 additions & 4 deletions sass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
#include "file.hpp"
#include "util.hpp"

#ifdef _MSC_VER
#define LIBSASS_VERSION "1.0.0"
#endif

extern "C" {
using namespace std;
using namespace Sass;
Expand Down
4 changes: 2 additions & 2 deletions sass_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ extern "C" {
string cwd(Sass::File::get_cwd());
JsonNode* json_err = json_mkobject();
json_append_member(json_err, "status", json_mknumber(1));
json_append_member(json_err, "file", json_mkstring(e.pstate.path.c_str()));
json_append_member(json_err, "file", json_mkstring(e.pstate.path));
json_append_member(json_err, "line", json_mknumber(e.pstate.line+1));
json_append_member(json_err, "column", json_mknumber(e.pstate.column+1));
json_append_member(json_err, "message", json_mkstring(e.message.c_str()));
Expand Down Expand Up @@ -278,7 +278,7 @@ extern "C" {
c_ctx->error_message = sass_strdup(msg_stream.str().c_str());
c_ctx->error_text = sass_strdup(e.message.c_str());
c_ctx->error_status = 1;
c_ctx->error_file = sass_strdup(e.pstate.path.c_str());
c_ctx->error_file = sass_strdup(e.pstate.path);
c_ctx->error_line = e.pstate.line+1;
c_ctx->error_column = e.pstate.column+1;
c_ctx->error_src = e.pstate.src;
Expand Down

0 comments on commit dd7e37e

Please sign in to comment.