Commit 863cddce by Aaron Leung

Trying out new scheme built-in function definitions. Allows built-ins to have…

Trying out new scheme built-in function definitions. Allows built-ins to have default args and whatnot, and to be specified more easily than before.
parent d74cdbb2
......@@ -90,6 +90,12 @@ namespace Sass {
function_env[f.name] = f;
}
inline void Context::register_function_2(const char* sig, Primitive_2 ip)
{
Function f(const_cast<char*>(sig), ip, *this);
function_env[f.name] = f;
}
inline void Context::register_overload_stub(string name)
{
function_env[name] = Function(name, true);
......@@ -98,6 +104,8 @@ namespace Sass {
void Context::register_functions()
{
using namespace Functions;
register_function_2(foo_sig, foo);
// RGB Functions
register_function(rgb_descriptor, rgb);
register_overload_stub("rgba");
......
......@@ -37,7 +37,8 @@ namespace Sass {
void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0, const char* img_path_str = 0);
~Context();
void register_function_2(const char* sig, Primitive_2 ip);
void register_function(Function_Descriptor d, Primitive ip);
void register_function(Function_Descriptor d, Primitive ip, size_t arity);
void register_overload_stub(string name);
......
......@@ -706,7 +706,23 @@ namespace Sass {
// primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{
if (f.primitive) {
if (f.primitive_2) {
// evaluate arguments in the current environment
for (size_t i = 0, S = args.size(); i < S; ++i) {
if (args[i].type() != Node::assignment) {
args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
}
else {
args[i][1] = eval(args[i][1], prefix, env, f_env, new_Node, ctx);
}
}
// bind arguments
Environment bindings;
bindings.link(env.global ? *env.global : env);
bind_arguments("function " + f.name, f.parameters, args, prefix, bindings, f_env, new_Node, ctx);
return f.primitive_2(f.parameter_names, bindings, new_Node);
}
else if (f.primitive) {
map<Token, Node> bindings;
// bind arguments
for (size_t i = 0, j = 0, S = args.size(); i < S; ++i) {
......
......@@ -5,6 +5,8 @@
#include "node_factory.hpp"
#include "functions.hpp"
#include "context.hpp"
#include "document.hpp"
#include "eval_apply.hpp"
#include "error.hpp"
#include <iostream>
......@@ -14,9 +16,27 @@ using std::cerr; using std::endl;
namespace Sass {
Function::Function(const char* signature, Primitive ip, Node_Factory& new_Node)
// this constructor needs context.hpp, so it can't be defined in functions.hpp
Function::Function(char* signature, Primitive_2 ip, Context& ctx)
: primitive_2(ip),
overloaded(false)
{
//Document sig_doc(Document::make_from_source_chars(
Document sig_doc(Document::make_from_source_chars(ctx, signature));
sig_doc.lex<Prelexer::identifier>();
name = sig_doc.lexed.to_string();
parameters = sig_doc.parse_parameters();
parameter_names = ctx.new_Node(Node::parameters, "[PRIMITIVE FUNCTIONS]", 0, parameters.size());
for (size_t i = 0, S = parameters.size(); i < S; ++i) {
Node param(parameters[i]);
if (param.type() == Node::variable) {
parameter_names << param;
}
else {
parameter_names << param[0];
// assuming default args for primitives can be evaluated only once at init
param[1] = eval(param[1], Node(), ctx.global_env, ctx.function_env, ctx.new_Node, ctx);
}
}
}
......@@ -30,9 +50,15 @@ namespace Sass {
throw Error(Error::evaluation, path, line, message);
}
extern const char foo_sig[] = "foo($x, $y, $z: hey hey)";
Node foo(const Node parameters, Environment& bindings, Node_Factory& new_Node) {
return Node();
extern const char foo_sig[] = "foo($x, $y, $z: \"hey\")";
Node foo(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node arg1(bindings[parameter_names[0].token()]);
Node arg2(bindings[parameter_names[1].token()]);
Node arg3(bindings[parameter_names[2].token()]);
Node cat(new_Node(Node::concatenation, arg1.path(), arg1.line(), 3));
cat << arg3 << arg2 << arg1;
return cat;
}
// RGB Functions ///////////////////////////////////////////////////////
......
......@@ -8,21 +8,25 @@
#endif
namespace Sass {
struct Environment;
struct Context;
using std::map;
typedef Node (*Primitive)(const Node, map<Token, Node>&, Node_Factory& new_Node);
typedef Node (*Primitive_2)(const Node, Environment&, Node_Factory&);
typedef const char* str;
typedef str Function_Descriptor[];
struct Environment;
struct Function {
string name;
// vector<Token> parameters;
Node parameters;
Node parameter_names;
Node definition;
Primitive primitive;
Primitive_2 primitive_2;
bool overloaded;
Function()
......@@ -34,6 +38,7 @@ namespace Sass {
parameters(def[1]),
definition(def),
primitive(0),
primitive_2(0),
overloaded(false)
{ }
......@@ -43,16 +48,18 @@ namespace Sass {
parameters(Node()),
definition(Node()),
primitive(0),
primitive_2(0),
overloaded(overloaded)
{ }
Function(const char* signature, Primitive ip, Node_Factory& new_Node);
Function(char* signature, Primitive_2 ip, Context& ctx);
Function(Function_Descriptor d, Primitive ip, Node_Factory& new_Node)
: name(d[0]),
parameters(new_Node(Node::parameters, "[PRIMITIVE FUNCTIONS]", 0, 0)),
definition(Node()),
primitive(ip),
primitive_2(0),
overloaded(false)
{
size_t len = 0;
......@@ -74,6 +81,9 @@ namespace Sass {
namespace Functions {
extern const char foo_sig[];
Node foo(const Node parameters, Environment& bindings, Node_Factory& new_Node);
// RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor;
......
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