Commit d008daf9 by Aaron Leung

Built-in function framework is in place. Had to jump through some hoops to…

Built-in function framework is in place. Had to jump through some hoops to resolve the usual #include dependency headaches.
parent 213cf18c
build: sassc.cpp document.cpp node.cpp values.cpp prelexer.cpp
g++ -o bin/sassc sassc.cpp document.cpp document_parser.cpp eval_apply.cpp node.cpp values.cpp prelexer.cpp
g++ -o bin/sassc sassc.cpp context.cpp functions.cpp document.cpp document_parser.cpp eval_apply.cpp node.cpp values.cpp prelexer.cpp
test: build
ruby spec.rb spec/basic/
......
#include "context.hpp"
#include <iostream>
using std::cerr; using std::endl;
namespace Sass {
Context::Context()
: global_env(Environment()),
function_env(map<string, Function>()),
source_refs(vector<char*>()),
ref_count(0)
{
register_functions();
}
Context::~Context()
{
for (int i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i];
}
}
inline void Context::register_function(Function_Descriptor d, Implementation ip)
{
function_env[d[0]] = Function(d, ip);
cerr << "Registered function: " << d[0] << endl;
cerr << "Verifying " << function_env[string(d[0])].name << endl;
}
void Context::register_functions()
{
using namespace Functions;
register_function(rgb_descriptor, rgb);
register_function(rgba_descriptor, rgba);
}
}
\ No newline at end of file
#define SASS_CONTEXT_INCLUDED
#include <map>
#include "functions.hpp"
namespace Sass {
......@@ -40,18 +41,12 @@ namespace Sass {
map<string, Function> function_env;
vector<char*> source_refs;
size_t ref_count;
Context()
: source_refs(vector<char*>()),
ref_count(0)
{ }
~Context()
{
for (int i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i];
}
}
Context();
~Context();
void register_function(Function_Descriptor d, Implementation ip);
void register_functions();
};
}
......@@ -524,20 +524,20 @@ namespace Sass {
return result;
}
if (lex< rgb_prefix >())
{
Node result(Node::numeric_color, line_number, 3);
lex< number >();
result << Node(line_number, std::atof(lexed.begin));
lex< exactly<','> >();
lex< number >();
result << Node(line_number, std::atof(lexed.begin));
lex< exactly<','> >();
lex< number >();
result << Node(line_number, std::atof(lexed.begin));
lex< exactly<')'> >();
return result;
}
// if (lex< rgb_prefix >())
// {
// Node result(Node::numeric_color, line_number, 3);
// lex< number >();
// result << Node(line_number, std::atof(lexed.begin));
// lex< exactly<','> >();
// lex< number >();
// result << Node(line_number, std::atof(lexed.begin));
// lex< exactly<','> >();
// lex< number >();
// result << Node(line_number, std::atof(lexed.begin));
// lex< exactly<')'> >();
// return result;
// }
if (peek< functional >())
{ return parse_function_call(); }
......@@ -575,6 +575,7 @@ namespace Sass {
Node args(parse_arguments());
Node call(Node::function_call, line_number, 2);
call << name << args;
call.eval_me = true;
return call;
}
......
......@@ -148,6 +148,7 @@ namespace Sass {
case Node::function_call: {
// TO DO: default-constructed Function should be a generic callback
cerr << "about to apply " << expr[0].content.token.to_string() << endl;
return apply_function(f_env[expr[0].content.token.to_string()], expr[1], env, f_env);
} break;
......@@ -289,8 +290,7 @@ namespace Sass {
Node apply_function(const Function& f, const Node& args, Environment& env, map<string, Function>& f_env)
{
Node params(f.parameters);
Environment bindings;
map<Token, Node> bindings;
// bind arguments
for (int i = 0, j = 0; i < args.size(); ++i) {
if (args[i].type == Node::assignment) {
......@@ -299,10 +299,8 @@ namespace Sass {
bindings[name] = eval(arg[1], env, f_env);
}
else {
// TO DO: ensure (j < params.size())
Node param(params[j]);
Token name(param.type == Node::variable ? param.content.token : param[0].content.token);
bindings[name] = eval(args[i], env, f_env);
// TO DO: ensure (j < f.parameters.size())
bindings[f.parameters[j]] = eval(args[i], env, f_env);
++j;
}
}
......
#include "functions.hpp"
#include "node.hpp"
#include <iostream>
using std::cerr; using std::endl;
namespace Sass {
namespace Functions {
extern const char* rgb_metadata[] = {
"rgb",
"$red",
"$green",
"$blue",
0
};
Node rgb(const vector<Token>& param_names, const Environment& bindings) {
Node color(Node::numeric_color, 0, 3);
color << bindings[param_names[0]]
<< bindings[param_names[1]]
<< bindings[param_names[2]];
return color;
}
extern const char* rgba_metadata[] = {
"rgba",
"$red",
"$green",
"$blue",
"$alpha",
0
};
Node rgba(const vector<Token>& param_names, const Environment& bindings) {
Node color(Node::numeric_color, 0, 3);
color << bindings[param_names[0]]
<< bindings[param_names[1]]
<< bindings[param_names[2]]
<< bindings[param_names[3]];
return color;
// TO DO: functions need to check the types of their arguments
Function_Descriptor rgb_descriptor =
{ "rgb", "$red", "$green", "$blue", 0 };
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings) {
cerr << "rgb arg count: " << bindings.size() << endl;
Node color(Node::numeric_color, 0, 3);
color << bindings[parameters[0]]
<< bindings[parameters[1]]
<< bindings[parameters[2]];
return color;
}
Function_Descriptor rgba_descriptor =
{ "rgba", "$red", "$green", "$blue", "$alpha", 0 };
Node rgba(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node color(Node::numeric_color, 0, 4);
color << bindings[parameters[0]]
<< bindings[parameters[1]]
<< bindings[parameters[2]]
<< bindings[parameters[3]];
return color;
}
}
}
\ No newline at end of file
#include <cstring>
#include <map>
#ifndef SASS_NODE_INCLUDED
#include "node.hpp"
#endif
namespace Sass {
using std::map;
struct Environment;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&);
typedef const char* str;
typedef str Function_Descriptor[];
struct Function {
typedef Node (*Primitive)(const Node&, const Environment&);
string name;
Node parameters;
vector<Token> param_names;
Primitive primitive;
vector<Token> parameters;
Implementation implementation;
Function()
{ }
{ /* TO DO: set up the generic callback here */ }
Function(string name, Node parameters, Primitive primitive)
: name(name), parameters(parameters), primitive(primitive)
{ }
Function(Function_Descriptor d, Implementation ip)
: name(d[0]),
parameters(vector<Token>()),
implementation(ip)
{
size_t len = 0;
while (d[len+1]) ++len;
parameters.reserve(len);
for (int i = 0; i < len; ++i) {
const char* p = d[i+1];
Token name(Token::make(p, p + std::strlen(p)));
parameters.push_back(name);
}
}
Node operator()(const Environment& bindings) const
{ return primitive(parameters, bindings); }
Node operator()(map<Token, Node>& bindings) const
{ return implementation(parameters, bindings); }
};
namespace Functions {
extern Function_Descriptor rgb_descriptor;
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings);
extern Function_Descriptor rgba_descriptor;
Node rgba(const vector<Token>& parameters, map<Token, Node>& bindings);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment