Commit 1f5eaff3 by Michael Mifsud Committed by GitHub

Merge pull request #1866 from xzyfer/bump-libsass

Bump LibSass to 3.5.0.beta.2
parents 71a7a84c 1b9970a4
{ {
"name": "node-sass", "name": "node-sass",
"version": "4.3.0", "version": "4.3.0",
"libsass": "3.4.3", "libsass": "3.5.0.beta.2",
"description": "Wrapper around libsass", "description": "Wrapper around libsass",
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/sass/node-sass/issues", "bugs": "https://github.com/sass/node-sass/issues",
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
], ],
'sources': [ 'sources': [
'libsass/src/ast.cpp', 'libsass/src/ast.cpp',
'libsass/src/ast_fwd_decl.cpp',
'libsass/src/base64vlq.cpp', 'libsass/src/base64vlq.cpp',
'libsass/src/bind.cpp', 'libsass/src/bind.cpp',
'libsass/src/cencode.c', 'libsass/src/cencode.c',
......
language: cpp language: cpp
sudo: false sudo: false
os:
- linux
- osx
compiler:
- gcc
- clang
# don't create redundant code coverage reports # don't create redundant code coverage reports
# - AUTOTOOLS=yes COVERAGE=yes BUILD=static # - AUTOTOOLS=yes COVERAGE=yes BUILD=static
...@@ -19,27 +12,53 @@ compiler: ...@@ -19,27 +12,53 @@ compiler:
# this will still catch all coding errors! # this will still catch all coding errors!
# - AUTOTOOLS=yes COVERAGE=no BUILD=static # - AUTOTOOLS=yes COVERAGE=no BUILD=static
env:
- AUTOTOOLS=no COVERAGE=no BUILD=shared
- AUTOTOOLS=no COVERAGE=yes BUILD=static
- AUTOTOOLS=yes COVERAGE=no BUILD=shared
# currenty there are various issues when # currenty there are various issues when
# built with coverage, clang and autotools # built with coverage, clang and autotools
# - AUTOTOOLS=yes COVERAGE=yes BUILD=shared # - AUTOTOOLS=yes COVERAGE=yes BUILD=shared
matrix: matrix:
exclude: include :
- compiler: clang - os: linux
env: AUTOTOOLS=yes COVERAGE=yes BUILD=static compiler: gcc
env: AUTOTOOLS=no COVERAGE=yes BUILD=static
- os: linux - os: linux
compiler: g++-5
env: AUTOTOOLS=yes COVERAGE=no BUILD=shared
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- os: linux
compiler: clang++-3.7
env: AUTOTOOLS=no COVERAGE=yes BUILD=static
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
packages:
- clang-3.7
- os: linux
compiler: clang
env: AUTOTOOLS=yes COVERAGE=no BUILD=shared
- os: osx
compiler: clang
env: AUTOTOOLS=no COVERAGE=no BUILD=shared env: AUTOTOOLS=no COVERAGE=no BUILD=shared
- os: osx - os: osx
compiler: gcc compiler: clang
env: AUTOTOOLS=no COVERAGE=yes BUILD=static
- os: osx - os: osx
env: AUTOTOOLS=no BUILD=static compiler: clang
env: AUTOTOOLS=yes COVERAGE=no BUILD=shared
script: ./script/ci-build-libsass script:
- ./script/ci-build-libsass
- ./script/ci-build-plugin math
- ./script/ci-build-plugin glob
- ./script/ci-build-plugin digest
- ./script/ci-build-plugin tests
before_install: ./script/ci-install-deps before_install: ./script/ci-install-deps
install: ./script/ci-install-compiler install: ./script/ci-install-compiler
after_success: ./script/ci-report-coverage after_success: ./script/ci-report-coverage
...@@ -4,7 +4,7 @@ AM_COPT = -Wall -O2 ...@@ -4,7 +4,7 @@ AM_COPT = -Wall -O2
AM_COVLDFLAGS = AM_COVLDFLAGS =
if ENABLE_COVERAGE if ENABLE_COVERAGE
AM_COPT = -O0 --coverage AM_COPT = -Wall -O1 -fno-omit-frame-pointer --coverage
AM_COVLDFLAGS += -lgcov AM_COVLDFLAGS += -lgcov
endif endif
...@@ -57,7 +57,7 @@ TESTS = \ ...@@ -57,7 +57,7 @@ TESTS = \
$(SASS_SPEC_PATH)/spec/scss-tests \ $(SASS_SPEC_PATH)/spec/scss-tests \
$(SASS_SPEC_PATH)/spec/types $(SASS_SPEC_PATH)/spec/types
SASS_TEST_FLAGS = -V 3.4 --impl libsass SASS_TEST_FLAGS = -V 3.5 --impl libsass
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) ./script/tap-driver LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) ./script/tap-driver
AM_LOG_FLAGS = -c ./tester $(LOG_FLAGS) AM_LOG_FLAGS = -c ./tester $(LOG_FLAGS)
if USE_TAP if USE_TAP
......
...@@ -15,10 +15,14 @@ INSTALL ?= install ...@@ -15,10 +15,14 @@ INSTALL ?= install
CFLAGS ?= -Wall CFLAGS ?= -Wall
CXXFLAGS ?= -Wall CXXFLAGS ?= -Wall
LDFLAGS ?= -Wall LDFLAGS ?= -Wall
ifneq "$(COVERAGE)" "yes" ifeq "x$(COVERAGE)" "x"
CFLAGS += -O2 CFLAGS += -O2
CXXFLAGS += -O2 CXXFLAGS += -O2
LDFLAGS += -O2 LDFLAGS += -O2
else
CFLAGS += -O1 -fno-omit-frame-pointer
CXXFLAGS += -O1 -fno-omit-frame-pointer
LDFLAGS += -O1 -fno-omit-frame-pointer
endif endif
LDFLAGS += -Wl,-undefined,error LDFLAGS += -Wl,-undefined,error
CAT ?= $(if $(filter $(OS),Windows_NT),type,cat) CAT ?= $(if $(filter $(OS),Windows_NT),type,cat)
...@@ -305,16 +309,16 @@ version: $(SASSC_BIN) ...@@ -305,16 +309,16 @@ version: $(SASSC_BIN)
$(SASSC_BIN) -v $(SASSC_BIN) -v
test: $(SASSC_BIN) test: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR) $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
test_build: $(SASSC_BIN) test_build: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR) $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
test_full: $(SASSC_BIN) test_full: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass --run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR) $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass --run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
test_probe: $(SASSC_BIN) test_probe: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR) $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
clean-objects: lib clean-objects: lib
-$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la -$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la
......
...@@ -13,6 +13,7 @@ SOURCES = \ ...@@ -13,6 +13,7 @@ SOURCES = \
functions.cpp \ functions.cpp \
color_maps.cpp \ color_maps.cpp \
environment.cpp \ environment.cpp \
ast_fwd_decl.cpp \
bind.cpp \ bind.cpp \
file.cpp \ file.cpp \
util.cpp \ util.cpp \
......
...@@ -65,7 +65,7 @@ test_script: ...@@ -65,7 +65,7 @@ test_script:
} }
$env:TargetPath = Join-Path $pwd.Path $env:TargetPath $env:TargetPath = Join-Path $pwd.Path $env:TargetPath
If (Test-Path "$env:TargetPath") { If (Test-Path "$env:TargetPath") {
ruby sass-spec/sass-spec.rb -V 3.4 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec ruby sass-spec/sass-spec.rb -V 3.5 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec
if(-not($?)) { if(-not($?)) {
echo "sass-spec tests failed" echo "sass-spec tests failed"
exit 1 exit 1
......
...@@ -121,8 +121,8 @@ if test "x$enable_cov" = "xyes"; then ...@@ -121,8 +121,8 @@ if test "x$enable_cov" = "xyes"; then
# Remove all optimization flags from C[XX]FLAGS # Remove all optimization flags from C[XX]FLAGS
changequote({,}) changequote({,})
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` CFLAGS=`echo "$CFLAGS -O1 -fno-omit-frame-pointer" | $SED -e 's/-O[0-9]*//g'`
CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9]*//g'` CXXFLAGS=`echo "$CXXFLAGS -O1 -fno-omit-frame-pointer" | $SED -e 's/-O[0-9]*//g'`
changequote([,]) changequote([,])
AC_SUBST(GCOV) AC_SUBST(GCOV)
......
...@@ -7,26 +7,35 @@ enum Sass_Input_Style { ...@@ -7,26 +7,35 @@ enum Sass_Input_Style {
SASS_CONTEXT_FOLDER SASS_CONTEXT_FOLDER
}; };
// simple linked list
struct string_list {
string_list* next;
char* string;
};
// sass config options structure // sass config options structure
struct Sass_Options { struct Sass_Inspect_Options {
// Precision for fractional numbers
int precision;
// Output style for the generated css code // Output style for the generated css code
// A value from above SASS_STYLE_* constants // A value from above SASS_STYLE_* constants
enum Sass_Output_Style output_style; enum Sass_Output_Style output_style;
// Precision for fractional numbers
int precision;
};
// sass config options structure
struct Sass_Output_Options : Sass_Inspect_Options {
// String to be used for indentation
const char* indent;
// String to be used to for line feeds
const char* linefeed;
// Emit comments in the generated CSS indicating // Emit comments in the generated CSS indicating
// the corresponding source line. // the corresponding source line.
bool source_comments; bool source_comments;
};
// sass config options structure
struct Sass_Options : Sass_Output_Options {
// embed sourceMappingUrl as data uri // embed sourceMappingUrl as data uri
bool source_map_embed; bool source_map_embed;
...@@ -56,15 +65,9 @@ struct Sass_Options { ...@@ -56,15 +65,9 @@ struct Sass_Options {
// information in source-maps etc. // information in source-maps etc.
char* output_path; char* output_path;
// String to be used for indentation
const char* indent;
// String to be used to for line feeds
const char* linefeed;
// Colon-separated list of paths // Colon-separated list of paths
// Semicolon-separated on Windows // Semicolon-separated on Windows
// Note: It may be better to use // Maybe use array interface instead?
// array interface instead
char* include_path; char* include_path;
char* plugin_path; char* plugin_path;
...@@ -82,10 +85,13 @@ struct Sass_Options { ...@@ -82,10 +85,13 @@ struct Sass_Options {
char* source_map_root; char* source_map_root;
// Custom functions that can be called from sccs code // Custom functions that can be called from sccs code
Sass_C_Function_List c_functions; Sass_Function_List c_functions;
// Callback to overload imports // Callback to overload imports
Sass_C_Import_Callback importer; Sass_Importer_List c_importers;
// List of custom headers
Sass_Importer_List c_headers;
}; };
...@@ -111,6 +117,7 @@ struct Sass_Context : Sass_Options ...@@ -111,6 +117,7 @@ struct Sass_Context : Sass_Options
char* error_file; char* error_file;
size_t error_line; size_t error_line;
size_t error_column; size_t error_column;
const char* error_src;
// report imported files // report imported files
char** included_files; char** included_files;
...@@ -130,6 +137,7 @@ struct Sass_Data_Context : Sass_Context { ...@@ -130,6 +137,7 @@ struct Sass_Data_Context : Sass_Context {
// provided source string // provided source string
char* source_string; char* source_string;
char* srcmap_string;
}; };
...@@ -147,9 +155,9 @@ struct Sass_Compiler { ...@@ -147,9 +155,9 @@ struct Sass_Compiler {
// original c context // original c context
Sass_Context* c_ctx; Sass_Context* c_ctx;
// Sass::Context // Sass::Context
void* cpp_ctx; Sass::Context* cpp_ctx;
// Sass::Block // Sass::Block
void* root; Sass::Block_Obj root;
}; };
``` ```
...@@ -207,6 +207,15 @@ size_t sass_context_get_error_column (struct Sass_Context* ctx); ...@@ -207,6 +207,15 @@ size_t sass_context_get_error_column (struct Sass_Context* ctx);
const char* sass_context_get_source_map_string (struct Sass_Context* ctx); const char* sass_context_get_source_map_string (struct Sass_Context* ctx);
char** sass_context_get_included_files (struct Sass_Context* ctx); char** sass_context_get_included_files (struct Sass_Context* ctx);
// Getters for Sass_Compiler options (query import stack)
size_t sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler);
Sass_Import_Entry sass_compiler_get_last_import(struct Sass_Compiler* compiler);
Sass_Import_Entry sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx);
// Getters for Sass_Compiler options (query function stack)
size_t sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler);
Sass_Callee_Entry sass_compiler_get_last_callee(struct Sass_Compiler* compiler);
Sass_Callee_Entry sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx);
// Take ownership of memory (value on context is set to 0) // Take ownership of memory (value on context is set to 0)
char* sass_context_take_error_json (struct Sass_Context* ctx); char* sass_context_take_error_json (struct Sass_Context* ctx);
char* sass_context_take_error_text (struct Sass_Context* ctx); char* sass_context_take_error_text (struct Sass_Context* ctx);
...@@ -214,10 +223,6 @@ char* sass_context_take_error_message (struct Sass_Context* ctx); ...@@ -214,10 +223,6 @@ char* sass_context_take_error_message (struct Sass_Context* ctx);
char* sass_context_take_error_file (struct Sass_Context* ctx); char* sass_context_take_error_file (struct Sass_Context* ctx);
char* sass_context_take_output_string (struct Sass_Context* ctx); char* sass_context_take_output_string (struct Sass_Context* ctx);
char* sass_context_take_source_map_string (struct Sass_Context* ctx); char* sass_context_take_source_map_string (struct Sass_Context* ctx);
// Push function for plugin/include paths (no manipulation support for now)
void sass_option_push_plugin_path (struct Sass_Options* options, const char* path);
void sass_option_push_include_path (struct Sass_Options* options, const char* path);
``` ```
### Sass Options API ### Sass Options API
...@@ -236,13 +241,18 @@ const char* sass_option_get_indent (struct Sass_Options* options); ...@@ -236,13 +241,18 @@ const char* sass_option_get_indent (struct Sass_Options* options);
const char* sass_option_get_linefeed (struct Sass_Options* options); const char* sass_option_get_linefeed (struct Sass_Options* options);
const char* sass_option_get_input_path (struct Sass_Options* options); const char* sass_option_get_input_path (struct Sass_Options* options);
const char* sass_option_get_output_path (struct Sass_Options* options); const char* sass_option_get_output_path (struct Sass_Options* options);
const char* sass_option_get_plugin_path (struct Sass_Options* options);
const char* sass_option_get_include_path (struct Sass_Options* options);
const char* sass_option_get_source_map_file (struct Sass_Options* options); const char* sass_option_get_source_map_file (struct Sass_Options* options);
const char* sass_option_get_source_map_root (struct Sass_Options* options); const char* sass_option_get_source_map_root (struct Sass_Options* options);
Sass_C_Function_List sass_option_get_c_functions (struct Sass_Options* options); Sass_C_Function_List sass_option_get_c_functions (struct Sass_Options* options);
Sass_C_Import_Callback sass_option_get_importer (struct Sass_Options* options); Sass_C_Import_Callback sass_option_get_importer (struct Sass_Options* options);
// Getters for Context_Option include path array
size_t sass_option_get_include_path_size(struct Sass_Options* options);
const char* sass_option_get_include_path(struct Sass_Options* options, size_t i);
// Plugin paths to load dynamic libraries work the same
size_t sass_option_get_plugin_path_size(struct Sass_Options* options);
const char* sass_option_get_plugin_path(struct Sass_Options* options, size_t i);
// Setters for Context_Option values // Setters for Context_Option values
void sass_option_set_precision (struct Sass_Options* options, int precision); void sass_option_set_precision (struct Sass_Options* options, int precision);
void sass_option_set_output_style (struct Sass_Options* options, enum Sass_Output_Style output_style); void sass_option_set_output_style (struct Sass_Options* options, enum Sass_Output_Style output_style);
...@@ -266,6 +276,16 @@ void sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callb ...@@ -266,6 +276,16 @@ void sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callb
// Push function for paths (no manipulation support for now) // Push function for paths (no manipulation support for now)
void sass_option_push_plugin_path (struct Sass_Options* options, const char* path); void sass_option_push_plugin_path (struct Sass_Options* options, const char* path);
void sass_option_push_include_path (struct Sass_Options* options, const char* path); void sass_option_push_include_path (struct Sass_Options* options, const char* path);
// Resolve a file via the given include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
char* sass_find_file (const char* path, struct Sass_Options* opt);
char* sass_find_include (const char* path, struct Sass_Options* opt);
// Resolve a file relative to last import or include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
char* sass_compiler_find_file (const char* path, struct Sass_Compiler* compiler);
char* sass_compiler_find_include (const char* path, struct Sass_Compiler* compiler);
``` ```
### More links ### More links
......
## Introduction ## Introduction
LibSass wouldn't be much good without a way to interface with it. These interface documentations describe the various functions and data structures available to implementers. They are split up over three major components, which have all their own source files (plus some common functionality). LibSass wouldn't be much good without a way to interface with it. These
interface documentations describe the various functions and data structures
available to implementers. They are split up over three major components, which
have all their own source files (plus some common functionality).
- [Sass Context](api-context.md) - Trigger and handle the main Sass compilation - [Sass Context](api-context.md) - Trigger and handle the main Sass compilation
- [Sass Value](api-value.md) - Exchange values and its format with LibSass - [Sass Value](api-value.md) - Exchange values and its format with LibSass
...@@ -41,7 +44,12 @@ gcc -Wall version.c -lsass -o version && ./version ...@@ -41,7 +44,12 @@ gcc -Wall version.c -lsass -o version && ./version
## Compiling your code ## Compiling your code
The most important is your sass file (or string of sass code). With this, you will want to start a LibSass compiler. Here is some pseudocode describing the process. The compiler has two different modes: direct input as a string with `Sass_Data_Context` or LibSass will do file reading for you by using `Sass_File_Context`. See the code for a list of options available [Sass_Options](https://github.com/sass/libsass/blob/36feef0/include/sass/interface.h#L18) The most important is your sass file (or string of sass code). With this, you
will want to start a LibSass compiler. Here is some pseudocode describing the
process. The compiler has two different modes: direct input as a string with
`Sass_Data_Context` or LibSass will do file reading for you by using
`Sass_File_Context`. See the code for a list of options available
[Sass_Options](https://github.com/sass/libsass/blob/36feef0/include/sass/interface.h#L18)
**Building a file compiler** **Building a file compiler**
...@@ -97,7 +105,9 @@ struct Sass_Data_context : Sass_Context; ...@@ -97,7 +105,9 @@ struct Sass_Data_context : Sass_Context;
This mirrors very well how `libsass` uses these structures. This mirrors very well how `libsass` uses these structures.
- `Sass_Options` holds everything you feed in before the compilation. It also hosts `input_path` and `output_path` options, because they are used to generate/calculate relative links in source-maps. The `input_path` is shared with `Sass_File_Context`. - `Sass_Options` holds everything you feed in before the compilation. It also hosts
`input_path` and `output_path` options, because they are used to generate/calculate
relative links in source-maps. The `input_path` is shared with `Sass_File_Context`.
- `Sass_Context` holds all the data returned by the compilation step. - `Sass_Context` holds all the data returned by the compilation step.
- `Sass_File_Context` is a specific implementation that requires no additional fields - `Sass_File_Context` is a specific implementation that requires no additional fields
- `Sass_Data_Context` is a specific implementation that adds the `input_source` field - `Sass_Data_Context` is a specific implementation that adds the `input_source` field
...@@ -106,8 +116,11 @@ Structs can be down-casted to access `context` or `options`! ...@@ -106,8 +116,11 @@ Structs can be down-casted to access `context` or `options`!
## Memory handling and life-cycles ## Memory handling and life-cycles
We keep memory around for as long as the main [context](api-context.md) object is not destroyed (`sass_delete_context`). LibSass will create copies of most inputs/options beside the main sass code. We keep memory around for as long as the main [context](api-context.md) object
You need to allocate and fill that buffer before passing it to LibSass. You may also overtake memory management from libsass for certain return values (i.e. `sass_context_take_output_string`). is not destroyed (`sass_delete_context`). LibSass will create copies of most
inputs/options beside the main sass code. You need to allocate and fill that
buffer before passing it to LibSass. You may also overtake memory management
from libsass for certain return values (i.e. `sass_context_take_output_string`).
```C ```C
// to allocate buffer to be filled // to allocate buffer to be filled
...@@ -125,9 +138,6 @@ void sass_free_memory(void* ptr); ...@@ -125,9 +138,6 @@ void sass_free_memory(void* ptr);
char* sass_string_unquote (const char* str); char* sass_string_unquote (const char* str);
char* sass_string_quote (const char* str, const char quote_mark); char* sass_string_quote (const char* str, const char quote_mark);
// Resolve a file via the given include paths in the include char* array
char* sass_resolve_file (const char* path, const char* incs[]);
// Get compiled libsass version // Get compiled libsass version
const char* libsass_version(void); const char* libsass_version(void);
...@@ -140,15 +150,25 @@ const char* libsass_language_version(void); ...@@ -140,15 +150,25 @@ const char* libsass_language_version(void);
**input_path** **input_path**
The `input_path` is part of `Sass_Options`, but it also is the main option for `Sass_File_Context`. It is also used to generate relative file links in source-maps. Therefore it is pretty usefull to pass this information if you have a `Sass_Data_Context` and know the original path. The `input_path` is part of `Sass_Options`, but it also is the main option for
`Sass_File_Context`. It is also used to generate relative file links in source-
maps. Therefore it is pretty usefull to pass this information if you have a
`Sass_Data_Context` and know the original path.
**output_path** **output_path**
Be aware that `libsass` does not write the output file itself. This option merely exists to give `libsass` the proper information to generate links in source-maps. The file has to be written to the disk by the binding/implementation. If the `output_path` is omitted, `libsass` tries to extrapolate one from the `input_path` by replacing (or adding) the file ending with `.css`. Be aware that `libsass` does not write the output file itself. This option
merely exists to give `libsass` the proper information to generate links in
source-maps. The file has to be written to the disk by the
binding/implementation. If the `output_path` is omitted, `libsass` tries to
extrapolate one from the `input_path` by replacing (or adding) the file ending
with `.css`.
## Error Codes ## Error Codes
The `error_code` is integer value which indicates the type of error that occurred inside the LibSass process. Following is the list of error codes along with the short description: The `error_code` is integer value which indicates the type of error that
occurred inside the LibSass process. Following is the list of error codes along
with the short description:
* 1: normal errors like parsing or `eval` errors * 1: normal errors like parsing or `eval` errors
* 2: bad allocation error (memory error) * 2: bad allocation error (memory error)
...@@ -156,11 +176,15 @@ The `error_code` is integer value which indicates the type of error that occurre ...@@ -156,11 +176,15 @@ The `error_code` is integer value which indicates the type of error that occurre
* 4: legacy string exceptions ( `throw const char*` or `std::string` ) * 4: legacy string exceptions ( `throw const char*` or `std::string` )
* 5: Some other unknown exception * 5: Some other unknown exception
Although for the API consumer, error codes do not offer much value except indicating whether *any* error occurred during the compilation, it helps debugging the LibSass internal code paths. Although for the API consumer, error codes do not offer much value except
indicating whether *any* error occurred during the compilation, it helps
debugging the LibSass internal code paths.
## Real-World Implementations ## Real-World Implementations
The proof is in the pudding, so we have highlighted a few implementations that should be on par with the latest LibSass interface version. Some of them may not have all features implemented! The proof is in the pudding, so we have highlighted a few implementations that
should be on par with the latest LibSass interface version. Some of them may not
have all features implemented!
1. [Perl Example](https://github.com/sass/perl-libsass/blob/master/lib/CSS/Sass.xs) 1. [Perl Example](https://github.com/sass/perl-libsass/blob/master/lib/CSS/Sass.xs)
2. [Go Example](http://godoc.org/github.com/wellington/go-libsass#example-Context-Compile) 2. [Go Example](http://godoc.org/github.com/wellington/go-libsass#example-Context-Compile)
...@@ -168,11 +192,20 @@ The proof is in the pudding, so we have highlighted a few implementations that s ...@@ -168,11 +192,20 @@ The proof is in the pudding, so we have highlighted a few implementations that s
## ABI forward compatibility ## ABI forward compatibility
We use a functional API to make dynamic linking more robust and future compatible. The API is not yet 100% stable, so we do not yet guarantee [ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) forward compatibility. We will do so, once we increase the shared library version above 1.0. We use a functional API to make dynamic linking more robust and future
compatible. The API is not yet 100% stable, so we do not yet guarantee
[ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) forward
compatibility.
## Plugins (experimental) ## Plugins (experimental)
LibSass can load plugins from directories. Just define `plugin_path` on context options to load all plugins from the given directories. To implement plugins, please consult the [[Wiki-Page for plugins|API-Plugins]]. LibSass can load plugins from directories. Just define `plugin_path` on context
options to load all plugins from the directories. To implement plugins, please
consult the following example implementations.
- https://github.com/mgreter/libsass-glob
- https://github.com/mgreter/libsass-math
- https://github.com/mgreter/libsass-digest
## Internal Structs ## Internal Structs
......
...@@ -11,7 +11,7 @@ union Sass_Value* call_fn_foo(const union Sass_Value* s_args, Sass_Function_Entr ...@@ -11,7 +11,7 @@ union Sass_Value* call_fn_foo(const union Sass_Value* s_args, Sass_Function_Entr
struct Sass_Context* ctx = sass_compiler_get_context(comp); struct Sass_Context* ctx = sass_compiler_get_context(comp);
struct Sass_Options* opts = sass_compiler_get_options(comp); struct Sass_Options* opts = sass_compiler_get_options(comp);
// get information about previous importer entry from the stack // get information about previous importer entry from the stack
struct Sass_Import* import = sass_compiler_get_last_import(comp); Sass_Import_Entry import = sass_compiler_get_last_import(comp);
const char* prev_abs_path = sass_import_get_abs_path(import); const char* prev_abs_path = sass_import_get_abs_path(import);
const char* prev_imp_path = sass_import_get_imp_path(import); const char* prev_imp_path = sass_import_get_imp_path(import);
// get the cookie from function descriptor // get the cookie from function descriptor
......
...@@ -30,17 +30,41 @@ typedef union Sass_Value* (*Sass_Function_Fn) ...@@ -30,17 +30,41 @@ typedef union Sass_Value* (*Sass_Function_Fn)
(const union Sass_Value*, Sass_Function_Entry cb, struct Sass_Compiler* compiler); (const union Sass_Value*, Sass_Function_Entry cb, struct Sass_Compiler* compiler);
// Creators for sass function list and function descriptors // Creators for sass function list and function descriptors
ADDAPI Sass_Function_List ADDCALL sass_make_function_list (size_t length); Sass_Function_List sass_make_function_list (size_t length);
ADDAPI Sass_Function_Entry ADDCALL sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie); Sass_Function_Entry sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie);
// In case you need to free them yourself
void sass_delete_function (Sass_Function_Entry entry);
void sass_delete_function_list (Sass_Function_List list);
// Setters and getters for callbacks on function lists // Setters and getters for callbacks on function lists
ADDAPI Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos); Sass_Function_Entry sass_function_get_list_entry(Sass_Function_List list, size_t pos);
ADDAPI void ADDCALL sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb); void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb);
// Setters to insert an entry into the import list (you may also use [] access directly)
// Since we are dealing with pointers they should have a guaranteed and fixed size
void sass_import_set_list_entry (Sass_Import_List list, size_t idx, Sass_Import_Entry entry);
Sass_Import_Entry sass_import_get_list_entry (Sass_Import_List list, size_t idx);
// Getters for custom function descriptors // Getters for custom function descriptors
ADDAPI const char* ADDCALL sass_function_get_signature (Sass_Function_Entry cb); const char* sass_function_get_signature (Sass_Function_Entry cb);
ADDAPI Sass_Function_Fn ADDCALL sass_function_get_function (Sass_Function_Entry cb); Sass_Function_Fn sass_function_get_function (Sass_Function_Entry cb);
ADDAPI void* ADDCALL sass_function_get_cookie (Sass_Function_Entry cb); void* sass_function_get_cookie (Sass_Function_Entry cb);
// Getters for callee entry
const char* sass_callee_get_name (Sass_Callee_Entry);
const char* sass_callee_get_path (Sass_Callee_Entry);
size_t sass_callee_get_line (Sass_Callee_Entry);
size_t sass_callee_get_column (Sass_Callee_Entry);
enum Sass_Callee_Type sass_callee_get_type (Sass_Callee_Entry);
Sass_Env_Frame sass_callee_get_env (Sass_Callee_Entry);
// Getters and Setters for environments (lexical, local and global)
union Sass_Value* sass_env_get_lexical (Sass_Env_Frame, const char*);
void sass_env_set_lexical (Sass_Env_Frame, const char*, union Sass_Value*);
union Sass_Value* sass_env_get_local (Sass_Env_Frame, const char*);
void sass_env_set_local (Sass_Env_Frame, const char*, union Sass_Value*);
union Sass_Value* sass_env_get_global (Sass_Env_Frame, const char*);
void sass_env_set_global (Sass_Env_Frame, const char*, union Sass_Value*);
``` ```
### More links ### More links
......
...@@ -5,7 +5,7 @@ By using custom importers, Sass stylesheets can be implemented in any possible w ...@@ -5,7 +5,7 @@ By using custom importers, Sass stylesheets can be implemented in any possible w
You actually have to return a list of imports, since some importers may want to import multiple files from one import statement (ie. a glob/star importer). The memory you pass with source and srcmap is taken over by LibSass and freed automatically when the import is done. You are also allowed to return `0` instead of a list, which will tell LibSass to handle the import by itself (as if no custom importer was in use). You actually have to return a list of imports, since some importers may want to import multiple files from one import statement (ie. a glob/star importer). The memory you pass with source and srcmap is taken over by LibSass and freed automatically when the import is done. You are also allowed to return `0` instead of a list, which will tell LibSass to handle the import by itself (as if no custom importer was in use).
```C ```C
struct Sass_Import** rv = sass_make_import_list(1); Sass_Import_Entry* rv = sass_make_import_list(1);
rv[0] = sass_make_import(rel, abs, source, srcmap); rv[0] = sass_make_import(rel, abs, source, srcmap);
``` ```
...@@ -31,7 +31,7 @@ struct Sass_C_Import_Descriptor; ...@@ -31,7 +31,7 @@ struct Sass_C_Import_Descriptor;
// Typedef defining the custom importer callback // Typedef defining the custom importer callback
typedef struct Sass_C_Import_Descriptor (*Sass_C_Import_Callback); typedef struct Sass_C_Import_Descriptor (*Sass_C_Import_Callback);
// Typedef defining the importer c function prototype // Typedef defining the importer c function prototype
typedef struct Sass_Import** (*Sass_C_Import_Fn) (const char* url, const char* prev, void* cookie); typedef Sass_Import_Entry* (*Sass_C_Import_Fn) (const char* url, const char* prev, void* cookie);
// Creators for custom importer callback (with some additional pointer) // Creators for custom importer callback (with some additional pointer)
// The pointer is mostly used to store the callback into the actual function // The pointer is mostly used to store the callback into the actual function
...@@ -45,38 +45,38 @@ void* sass_import_get_cookie (Sass_C_Import_Callback fn); ...@@ -45,38 +45,38 @@ void* sass_import_get_cookie (Sass_C_Import_Callback fn);
void sass_delete_importer (Sass_C_Import_Callback fn); void sass_delete_importer (Sass_C_Import_Callback fn);
// Creator for sass custom importer return argument list // Creator for sass custom importer return argument list
struct Sass_Import** sass_make_import_list (size_t length); Sass_Import_Entry* sass_make_import_list (size_t length);
// Creator for a single import entry returned by the custom importer inside the list // Creator for a single import entry returned by the custom importer inside the list
struct Sass_Import* sass_make_import_entry (const char* path, char* source, char* srcmap); Sass_Import_Entry sass_make_import_entry (const char* path, char* source, char* srcmap);
struct Sass_Import* sass_make_import (const char* rel, const char* abs, char* source, char* srcmap); Sass_Import_Entry sass_make_import (const char* rel, const char* abs, char* source, char* srcmap);
// set error message to abort import and to print out a message (path from existing object is used in output) // set error message to abort import and to print out a message (path from existing object is used in output)
struct Sass_Import* sass_import_set_error(struct Sass_Import* import, const char* message, size_t line, size_t col); Sass_Import_Entry sass_import_set_error(Sass_Import_Entry import, const char* message, size_t line, size_t col);
// Setters to insert an entry into the import list (you may also use [] access directly) // Setters to insert an entry into the import list (you may also use [] access directly)
// Since we are dealing with pointers they should have a guaranteed and fixed size // Since we are dealing with pointers they should have a guaranteed and fixed size
void sass_import_set_list_entry (struct Sass_Import** list, size_t idx, struct Sass_Import* entry); void sass_import_set_list_entry (Sass_Import_Entry* list, size_t idx, Sass_Import_Entry entry);
struct Sass_Import* sass_import_get_list_entry (struct Sass_Import** list, size_t idx); Sass_Import_Entry sass_import_get_list_entry (Sass_Import_Entry* list, size_t idx);
// Getters for import entry // Getters for import entry
const char* sass_import_get_rel_path (struct Sass_Import*); const char* sass_import_get_imp_path (Sass_Import_Entry);
const char* sass_import_get_abs_path (struct Sass_Import*); const char* sass_import_get_abs_path (Sass_Import_Entry);
const char* sass_import_get_source (struct Sass_Import*); const char* sass_import_get_source (Sass_Import_Entry);
const char* sass_import_get_srcmap (struct Sass_Import*); const char* sass_import_get_srcmap (Sass_Import_Entry);
// Explicit functions to take ownership of these items // Explicit functions to take ownership of these items
// The property on our struct will be reset to NULL // The property on our struct will be reset to NULL
char* sass_import_take_source (struct Sass_Import*); char* sass_import_take_source (Sass_Import_Entry);
char* sass_import_take_srcmap (struct Sass_Import*); char* sass_import_take_srcmap (Sass_Import_Entry);
// Getters for import error entries // Getters for import error entries
size_t sass_import_get_error_line (struct Sass_Import*); size_t sass_import_get_error_line (Sass_Import_Entry);
size_t sass_import_get_error_column (struct Sass_Import*); size_t sass_import_get_error_column (Sass_Import_Entry);
const char* sass_import_get_error_message (struct Sass_Import*); const char* sass_import_get_error_message (Sass_Import_Entry);
// Deallocator for associated memory (incl. entries) // Deallocator for associated memory (incl. entries)
void sass_delete_import_list (struct Sass_Import**); void sass_delete_import_list (Sass_Import_Entry*);
// Just in case we have some stray import structs // Just in case we have some stray import structs
void sass_delete_import (struct Sass_Import*); void sass_delete_import (Sass_Import_Entry);
``` ```
### More links ### More links
......
...@@ -58,7 +58,7 @@ union Sass_Value* sass_make_string (const char* val); ...@@ -58,7 +58,7 @@ union Sass_Value* sass_make_string (const char* val);
union Sass_Value* sass_make_qstring (const char* val); union Sass_Value* sass_make_qstring (const char* val);
union Sass_Value* sass_make_number (double val, const char* unit); union Sass_Value* sass_make_number (double val, const char* unit);
union Sass_Value* sass_make_color (double r, double g, double b, double a); union Sass_Value* sass_make_color (double r, double g, double b, double a);
union Sass_Value* sass_make_list (size_t len, enum Sass_Separator sep); union Sass_Value* sass_make_list (size_t len, enum Sass_Separator sep, bool is_bracketed);
union Sass_Value* sass_make_map (size_t len); union Sass_Value* sass_make_map (size_t len);
union Sass_Value* sass_make_error (const char* msg); union Sass_Value* sass_make_error (const char* msg);
union Sass_Value* sass_make_warning (const char* msg); union Sass_Value* sass_make_warning (const char* msg);
...@@ -124,6 +124,8 @@ size_t sass_list_get_length (const union Sass_Value* v); ...@@ -124,6 +124,8 @@ size_t sass_list_get_length (const union Sass_Value* v);
// Getters and setters for Sass_List // Getters and setters for Sass_List
enum Sass_Separator sass_list_get_separator (const union Sass_Value* v); enum Sass_Separator sass_list_get_separator (const union Sass_Value* v);
void sass_list_set_separator (union Sass_Value* v, enum Sass_Separator value); void sass_list_set_separator (union Sass_Value* v, enum Sass_Separator value);
bool sass_list_get_is_bracketed (const union Sass_Value* v);
void sass_list_set_is_bracketed (union Sass_Value* v, bool value);
// Getters and setters for Sass_List values // Getters and setters for Sass_List values
union Sass_Value* sass_list_get_value (const union Sass_Value* v, size_t i); union Sass_Value* sass_list_get_value (const union Sass_Value* v, size_t i);
void sass_list_set_value (union Sass_Value* v, size_t i, union Sass_Value* value); void sass_list_set_value (union Sass_Value* v, size_t i, union Sass_Value* value);
......
...@@ -130,7 +130,7 @@ cd libsass ...@@ -130,7 +130,7 @@ cd libsass
REM set PATH=%PATH%;%PROGRAMFILES%\MSBuild\12.0\Bin REM set PATH=%PATH%;%PROGRAMFILES%\MSBuild\12.0\Bin
msbuild /m:4 /p:Configuration=Release win\libsass.sln msbuild /m:4 /p:Configuration=Release win\libsass.sln
REM running the spec test-suite manually (needs ruby and minitest gem) REM running the spec test-suite manually (needs ruby and minitest gem)
ruby sass-spec\sass-spec.rb -V 3.4 -c win\bin\sassc.exe -s --impl libsass sass-spec/spec ruby sass-spec\sass-spec.rb -V 3.5 -c win\bin\sassc.exe -s --impl libsass sass-spec/spec
cd .. cd ..
``` ```
......
...@@ -45,14 +45,16 @@ The cookie can hold any pointer you want. In the `perl-libsass` implementation i ...@@ -45,14 +45,16 @@ The cookie can hold any pointer you want. In the `perl-libsass` implementation i
```C ```C
// allocate memory (copies passed strings) // allocate memory (copies passed strings)
union Sass_Value* make_sass_boolean (int val); union Sass_Value* sass_make_null (void);
union Sass_Value* make_sass_number (double val, const char* unit); union Sass_Value* sass_make_boolean (bool val);
union Sass_Value* make_sass_color (double r, double g, double b, double a); union Sass_Value* sass_make_string (const char* val);
union Sass_Value* make_sass_string (const char* val); union Sass_Value* sass_make_qstring (const char* val);
union Sass_Value* make_sass_list (size_t len, enum Sass_Separator sep); union Sass_Value* sass_make_number (double val, const char* unit);
union Sass_Value* make_sass_map (size_t len); union Sass_Value* sass_make_color (double r, double g, double b, double a);
union Sass_Value* make_sass_null (); union Sass_Value* sass_make_list (size_t len, enum Sass_Separator sep, bool is_bracketed);
union Sass_Value* make_sass_error (const char* msg); union Sass_Value* sass_make_map (size_t len);
union Sass_Value* sass_make_error (const char* msg);
union Sass_Value* sass_make_warning (const char* msg);
// Make a deep cloned copy of the given sass value // Make a deep cloned copy of the given sass value
union Sass_Value* sass_clone_value (const union Sass_Value* val); union Sass_Value* sass_clone_value (const union Sass_Value* val);
......
...@@ -75,9 +75,6 @@ ADDAPI void ADDCALL sass_free_memory(void* ptr); ...@@ -75,9 +75,6 @@ ADDAPI void ADDCALL sass_free_memory(void* ptr);
ADDAPI char* ADDCALL sass_string_quote (const char* str, const char quote_mark); ADDAPI char* ADDCALL sass_string_quote (const char* str, const char quote_mark);
ADDAPI char* ADDCALL sass_string_unquote (const char* str); ADDAPI char* ADDCALL sass_string_unquote (const char* str);
// Resolve a file via the given include paths in the include char* array
ADDAPI char* ADDCALL sass_resolve_file (const char* path, const char* incs[]);
// Implemented sass language version // Implemented sass language version
// Hardcoded version 3.4 for time being // Hardcoded version 3.4 for time being
ADDAPI const char* ADDCALL libsass_version(void); ADDAPI const char* ADDCALL libsass_version(void);
......
...@@ -81,8 +81,6 @@ ADDAPI const char* ADDCALL sass_option_get_indent (struct Sass_Options* options) ...@@ -81,8 +81,6 @@ ADDAPI const char* ADDCALL sass_option_get_indent (struct Sass_Options* options)
ADDAPI const char* ADDCALL sass_option_get_linefeed (struct Sass_Options* options); ADDAPI const char* ADDCALL sass_option_get_linefeed (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_input_path (struct Sass_Options* options); ADDAPI const char* ADDCALL sass_option_get_input_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_output_path (struct Sass_Options* options); ADDAPI const char* ADDCALL sass_option_get_output_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_plugin_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_include_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_source_map_file (struct Sass_Options* options); ADDAPI const char* ADDCALL sass_option_get_source_map_file (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_source_map_root (struct Sass_Options* options); ADDAPI const char* ADDCALL sass_option_get_source_map_root (struct Sass_Options* options);
ADDAPI Sass_Importer_List ADDCALL sass_option_get_c_headers (struct Sass_Options* options); ADDAPI Sass_Importer_List ADDCALL sass_option_get_c_headers (struct Sass_Options* options);
...@@ -124,6 +122,10 @@ ADDAPI size_t ADDCALL sass_context_get_error_column (struct Sass_Context* ctx); ...@@ -124,6 +122,10 @@ ADDAPI size_t ADDCALL sass_context_get_error_column (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_source_map_string (struct Sass_Context* ctx); ADDAPI const char* ADDCALL sass_context_get_source_map_string (struct Sass_Context* ctx);
ADDAPI char** ADDCALL sass_context_get_included_files (struct Sass_Context* ctx); ADDAPI char** ADDCALL sass_context_get_included_files (struct Sass_Context* ctx);
// Getters for options include path array
ADDAPI size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i);
// Calculate the size of the stored null terminated array // Calculate the size of the stored null terminated array
ADDAPI size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx); ADDAPI size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx);
...@@ -143,11 +145,24 @@ ADDAPI struct Sass_Options* ADDCALL sass_compiler_get_options(struct Sass_Compil ...@@ -143,11 +145,24 @@ ADDAPI struct Sass_Options* ADDCALL sass_compiler_get_options(struct Sass_Compil
ADDAPI size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler); ADDAPI size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler);
ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler); ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler);
ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx); ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx);
ADDAPI size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler);
ADDAPI Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler);
ADDAPI Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx);
// Push function for paths (no manipulation support for now) // Push function for paths (no manipulation support for now)
ADDAPI void ADDCALL sass_option_push_plugin_path (struct Sass_Options* options, const char* path); ADDAPI void ADDCALL sass_option_push_plugin_path (struct Sass_Options* options, const char* path);
ADDAPI void ADDCALL sass_option_push_include_path (struct Sass_Options* options, const char* path); ADDAPI void ADDCALL sass_option_push_include_path (struct Sass_Options* options, const char* path);
// Resolve a file via the given include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
ADDAPI char* ADDCALL sass_find_file (const char* path, struct Sass_Options* opt);
ADDAPI char* ADDCALL sass_find_include (const char* path, struct Sass_Options* opt);
// Resolve a file relative to last import or include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
ADDAPI char* ADDCALL sass_compiler_find_file (const char* path, struct Sass_Compiler* compiler);
ADDAPI char* ADDCALL sass_compiler_find_include (const char* path, struct Sass_Compiler* compiler);
#ifdef __cplusplus #ifdef __cplusplus
} // __cplusplus defined. } // __cplusplus defined.
#endif #endif
......
...@@ -11,12 +11,18 @@ extern "C" { ...@@ -11,12 +11,18 @@ extern "C" {
// Forward declaration // Forward declaration
struct Sass_Env;
struct Sass_Callee;
struct Sass_Import; struct Sass_Import;
struct Sass_Options; struct Sass_Options;
struct Sass_Compiler; struct Sass_Compiler;
struct Sass_Importer; struct Sass_Importer;
struct Sass_Function; struct Sass_Function;
// Typedef helpers for callee lists
typedef struct Sass_Env (*Sass_Env_Frame);
// Typedef helpers for callee lists
typedef struct Sass_Callee (*Sass_Callee_Entry);
// Typedef helpers for import lists // Typedef helpers for import lists
typedef struct Sass_Import (*Sass_Import_Entry); typedef struct Sass_Import (*Sass_Import_Entry);
typedef struct Sass_Import* (*Sass_Import_List); typedef struct Sass_Import* (*Sass_Import_List);
...@@ -34,11 +40,18 @@ typedef struct Sass_Function* (*Sass_Function_List); ...@@ -34,11 +40,18 @@ typedef struct Sass_Function* (*Sass_Function_List);
typedef union Sass_Value* (*Sass_Function_Fn) typedef union Sass_Value* (*Sass_Function_Fn)
(const union Sass_Value*, Sass_Function_Entry cb, struct Sass_Compiler* compiler); (const union Sass_Value*, Sass_Function_Entry cb, struct Sass_Compiler* compiler);
// Type of function calls
enum Sass_Callee_Type {
SASS_CALLEE_MIXIN,
SASS_CALLEE_FUNCTION,
SASS_CALLEE_C_FUNCTION,
};
// Creator for sass custom importer return argument list // Creator for sass custom importer return argument list
ADDAPI Sass_Importer_List ADDCALL sass_make_importer_list (size_t length); ADDAPI Sass_Importer_List ADDCALL sass_make_importer_list (size_t length);
ADDAPI Sass_Importer_Entry ADDCALL sass_importer_get_list_entry (Sass_Importer_List list, size_t idx); ADDAPI Sass_Importer_Entry ADDCALL sass_importer_get_list_entry (Sass_Importer_List list, size_t idx);
ADDAPI void ADDCALL sass_importer_set_list_entry (Sass_Importer_List list, size_t idx, Sass_Importer_Entry entry); ADDAPI void ADDCALL sass_importer_set_list_entry (Sass_Importer_List list, size_t idx, Sass_Importer_Entry entry);
ADDAPI void ADDCALL sass_delete_importer_list (Sass_Importer_List list);
// Creators for custom importer callback (with some additional pointer) // Creators for custom importer callback (with some additional pointer)
...@@ -66,6 +79,22 @@ ADDAPI Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import, ...@@ -66,6 +79,22 @@ ADDAPI Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import,
ADDAPI void ADDCALL sass_import_set_list_entry (Sass_Import_List list, size_t idx, Sass_Import_Entry entry); ADDAPI void ADDCALL sass_import_set_list_entry (Sass_Import_List list, size_t idx, Sass_Import_Entry entry);
ADDAPI Sass_Import_Entry ADDCALL sass_import_get_list_entry (Sass_Import_List list, size_t idx); ADDAPI Sass_Import_Entry ADDCALL sass_import_get_list_entry (Sass_Import_List list, size_t idx);
// Getters for callee entry
ADDAPI const char* ADDCALL sass_callee_get_name (Sass_Callee_Entry);
ADDAPI const char* ADDCALL sass_callee_get_path (Sass_Callee_Entry);
ADDAPI size_t ADDCALL sass_callee_get_line (Sass_Callee_Entry);
ADDAPI size_t ADDCALL sass_callee_get_column (Sass_Callee_Entry);
ADDAPI enum Sass_Callee_Type ADDCALL sass_callee_get_type (Sass_Callee_Entry);
ADDAPI Sass_Env_Frame ADDCALL sass_callee_get_env (Sass_Callee_Entry);
// Getters and Setters for environments (lexical, local and global)
ADDAPI union Sass_Value* ADDCALL sass_env_get_lexical (Sass_Env_Frame, const char*);
ADDAPI void ADDCALL sass_env_set_lexical (Sass_Env_Frame, const char*, union Sass_Value*);
ADDAPI union Sass_Value* ADDCALL sass_env_get_local (Sass_Env_Frame, const char*);
ADDAPI void ADDCALL sass_env_set_local (Sass_Env_Frame, const char*, union Sass_Value*);
ADDAPI union Sass_Value* ADDCALL sass_env_get_global (Sass_Env_Frame, const char*);
ADDAPI void ADDCALL sass_env_set_global (Sass_Env_Frame, const char*, union Sass_Value*);
// Getters for import entry // Getters for import entry
ADDAPI const char* ADDCALL sass_import_get_imp_path (Sass_Import_Entry); ADDAPI const char* ADDCALL sass_import_get_imp_path (Sass_Import_Entry);
ADDAPI const char* ADDCALL sass_import_get_abs_path (Sass_Import_Entry); ADDAPI const char* ADDCALL sass_import_get_abs_path (Sass_Import_Entry);
...@@ -90,6 +119,8 @@ ADDAPI void ADDCALL sass_delete_import (Sass_Import_Entry); ...@@ -90,6 +119,8 @@ ADDAPI void ADDCALL sass_delete_import (Sass_Import_Entry);
// Creators for sass function list and function descriptors // Creators for sass function list and function descriptors
ADDAPI Sass_Function_List ADDCALL sass_make_function_list (size_t length); ADDAPI Sass_Function_List ADDCALL sass_make_function_list (size_t length);
ADDAPI Sass_Function_Entry ADDCALL sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie); ADDAPI Sass_Function_Entry ADDCALL sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie);
ADDAPI void ADDCALL sass_delete_function (Sass_Function_Entry entry);
ADDAPI void ADDCALL sass_delete_function_list (Sass_Function_List list);
// Setters and getters for callbacks on function lists // Setters and getters for callbacks on function lists
ADDAPI Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos); ADDAPI Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos);
......
...@@ -50,7 +50,7 @@ ADDAPI union Sass_Value* ADDCALL sass_make_string (const char* val); ...@@ -50,7 +50,7 @@ ADDAPI union Sass_Value* ADDCALL sass_make_string (const char* val);
ADDAPI union Sass_Value* ADDCALL sass_make_qstring (const char* val); ADDAPI union Sass_Value* ADDCALL sass_make_qstring (const char* val);
ADDAPI union Sass_Value* ADDCALL sass_make_number (double val, const char* unit); ADDAPI union Sass_Value* ADDCALL sass_make_number (double val, const char* unit);
ADDAPI union Sass_Value* ADDCALL sass_make_color (double r, double g, double b, double a); ADDAPI union Sass_Value* ADDCALL sass_make_color (double r, double g, double b, double a);
ADDAPI union Sass_Value* ADDCALL sass_make_list (size_t len, enum Sass_Separator sep); ADDAPI union Sass_Value* ADDCALL sass_make_list (size_t len, enum Sass_Separator sep, bool is_bracketed);
ADDAPI union Sass_Value* ADDCALL sass_make_map (size_t len); ADDAPI union Sass_Value* ADDCALL sass_make_map (size_t len);
ADDAPI union Sass_Value* ADDCALL sass_make_error (const char* msg); ADDAPI union Sass_Value* ADDCALL sass_make_error (const char* msg);
ADDAPI union Sass_Value* ADDCALL sass_make_warning (const char* msg); ADDAPI union Sass_Value* ADDCALL sass_make_warning (const char* msg);
...@@ -116,6 +116,8 @@ ADDAPI size_t ADDCALL sass_list_get_length (const union Sass_Value* v); ...@@ -116,6 +116,8 @@ ADDAPI size_t ADDCALL sass_list_get_length (const union Sass_Value* v);
// Getters and setters for Sass_List // Getters and setters for Sass_List
ADDAPI enum Sass_Separator ADDCALL sass_list_get_separator (const union Sass_Value* v); ADDAPI enum Sass_Separator ADDCALL sass_list_get_separator (const union Sass_Value* v);
ADDAPI void ADDCALL sass_list_set_separator (union Sass_Value* v, enum Sass_Separator value); ADDAPI void ADDCALL sass_list_set_separator (union Sass_Value* v, enum Sass_Separator value);
ADDAPI bool ADDCALL sass_list_get_is_bracketed (const union Sass_Value* v);
ADDAPI void ADDCALL sass_list_set_is_bracketed (union Sass_Value* v, bool value);
// Getters and setters for Sass_List values // Getters and setters for Sass_List values
ADDAPI union Sass_Value* ADDCALL sass_list_get_value (const union Sass_Value* v, size_t i); ADDAPI union Sass_Value* ADDCALL sass_list_get_value (const union Sass_Value* v, size_t i);
ADDAPI void ADDCALL sass_list_set_value (union Sass_Value* v, size_t i, union Sass_Value* value); ADDAPI void ADDCALL sass_list_set_value (union Sass_Value* v, size_t i, union Sass_Value* value);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#endif #endif
#ifndef LIBSASS_LANGUAGE_VERSION #ifndef LIBSASS_LANGUAGE_VERSION
#define LIBSASS_LANGUAGE_VERSION "3.4" #define LIBSASS_LANGUAGE_VERSION "3.5"
#endif #endif
#endif #endif
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#endif #endif
#ifndef LIBSASS_LANGUAGE_VERSION #ifndef LIBSASS_LANGUAGE_VERSION
#define LIBSASS_LANGUAGE_VERSION "3.4" #define LIBSASS_LANGUAGE_VERSION "3.5"
#endif #endif
#endif #endif
...@@ -18,9 +18,14 @@ if [ "x$TRAVIS_OS_NAME" == "x" ]; then export TRAVIS_OS_NAME=`uname -s | perl -n ...@@ -18,9 +18,14 @@ if [ "x$TRAVIS_OS_NAME" == "x" ]; then export TRAVIS_OS_NAME=`uname -s | perl -n
if [ "x$COVERAGE" == "xyes" ]; then if [ "x$COVERAGE" == "xyes" ]; then
COVERAGE_OPT="--enable-coverage" COVERAGE_OPT="--enable-coverage"
export EXTRA_CFLAGS="--coverage" export EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage"
export EXTRA_CXXFLAGS="--coverage" export EXTRA_CXXFLAGS="-fprofile-arcs -ftest-coverage"
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
# osx doesn't seem to know gcov lib?
export EXTRA_LDFLAGS="--coverage" export EXTRA_LDFLAGS="--coverage"
else
export EXTRA_LDFLAGS="-lgcov --coverage"
fi
else else
COVERAGE_OPT="--disable-coverage" COVERAGE_OPT="--disable-coverage"
fi fi
...@@ -37,7 +42,7 @@ fi ...@@ -37,7 +42,7 @@ fi
if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
MAKE_OPTS="$MAKE_OPTS -j1 V=1" MAKE_OPTS="$MAKE_OPTS -j1 V=1"
else else
MAKE_OPTS="$MAKE_OPTS -j3 V=1" MAKE_OPTS="$MAKE_OPTS -j5 V=1"
fi fi
if [ "x$PREFIX" == "x" ]; then if [ "x$PREFIX" == "x" ]; then
......
#!/bin/bash
PLUGIN=$1
RUBY_BIN=ruby
SASS_SPEC_PATH=sass-spec
SASSC_BIN=sassc/bin/sassc
SASS_SPEC_SPEC_DIR=plugins/libsass-${PLUGIN}/test
if [ -e ./tester ] ; then
SASSC_BIN=./tester
fi
if [ -d ./build/lib ] ; then
cp -a build/lib lib
fi
if [ "x$1" == "x" ] ; then
echo "No plugin name given"
exit 1
fi
if [ "x$COVERAGE" == "0" ] ; then
unset COVERAGE
fi
export EXTRA_CFLAGS=""
export EXTRA_CXXFLAGS=""
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
# osx doesn't seem to know gcov lib?
export EXTRA_LDFLAGS="--coverage"
else
export EXTRA_LDFLAGS="-lgcov --coverage"
fi
mkdir -p plugins
if [ ! -d plugins/libsass-${PLUGIN} ] ; then
git clone https://github.com/mgreter/libsass-${PLUGIN} plugins/libsass-${PLUGIN}
fi
if [ ! -d plugins/libsass-${PLUGIN}/build ] ; then
mkdir plugins/libsass-${PLUGIN}/build
fi
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
cd plugins/libsass-${PLUGIN}/build
cmake -G "Unix Makefiles" -D LIBSASS_DIR="../../.." ..
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
make VERBOSE=1 -j2
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
cd ../../..
# glob only works on paths relative to imports
if [ "x$PLUGIN" == "xglob" ]; then
${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss > ${SASS_SPEC_SPEC_DIR}/basic/result.css
${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss --sourcemap > /dev/null
else
cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic > ${SASS_SPEC_SPEC_DIR}/basic/result.css
cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic --sourcemap > /dev/null
fi
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
diff ${SASS_SPEC_SPEC_DIR}/basic/expected_output.css ${SASS_SPEC_SPEC_DIR}/basic/result.css
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
if [ "x$COVERAGE" = "xyes" ]; then if [ "x$COVERAGE" = "xyes" ]; then
# find / -name "gcovr"
# find / -name "coveralls"
# this is only needed for mac os x builds!
PATH=$PATH:/Users/travis/Library/Python/2.7/bin/
# exclude some directories from profiling (.libs is from autotools) # exclude some directories from profiling (.libs is from autotools)
export EXCLUDE_COVERAGE="--exclude plugins export EXCLUDE_COVERAGE="--exclude plugins
--exclude sassc/sassc.c --exclude sassc/sassc.c
...@@ -21,10 +27,14 @@ if [ "x$COVERAGE" = "xyes" ]; then ...@@ -21,10 +27,14 @@ if [ "x$COVERAGE" = "xyes" ]; then
--exclude src/test --exclude src/test
--exclude src/posix --exclude src/posix
--exclude src/debugger.hpp" --exclude src/debugger.hpp"
# debug via gcovr # debug used gcov version
# option not available on mac
if [ "$TRAVIS_OS_NAME" != "osx" ]; then
gcov -v gcov -v
fi
# create summarized report
gcovr -r . gcovr -r .
# generate and submit report to coveralls.io # submit report to coveralls.io
coveralls $EXCLUDE_COVERAGE --gcov-options '\-lp' coveralls $EXCLUDE_COVERAGE --gcov-options '\-lp'
else else
......
...@@ -34,7 +34,7 @@ include $(top_srcdir)/Makefile.conf ...@@ -34,7 +34,7 @@ include $(top_srcdir)/Makefile.conf
libsass_la_SOURCES = ${CSOURCES} ${SOURCES} libsass_la_SOURCES = ${CSOURCES} ${SOURCES}
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 0:9:0 libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
if ENABLE_TESTS if ENABLE_TESTS
if ENABLE_COVERAGE if ENABLE_COVERAGE
......
...@@ -44,7 +44,7 @@ public:\ ...@@ -44,7 +44,7 @@ public:\
type name(type name##__) { return name##_ = name##__; }\ type name(type name##__) { return name##_ = name##__; }\
private: private:
#define ADD_HASHED(type, name)\ #define HASH_PROPERTY(type, name)\
protected:\ protected:\
type name##_;\ type name##_;\
public:\ public:\
...@@ -52,4 +52,20 @@ public:\ ...@@ -52,4 +52,20 @@ public:\
type name(type name##__) { hash_ = 0; return name##_ = name##__; }\ type name(type name##__) { hash_ = 0; return name##_ = name##__; }\
private: private:
#define ADD_CONSTREF(type, name) \
protected: \
type name##_; \
public: \
const type& name() const { return name##_; } \
void name(type name##__) { name##_ = name##__; } \
private:
#define HASH_CONSTREF(type, name) \
protected: \
type name##_; \
public: \
const type& name() const { return name##_; } \
void name(type name##__) { hash_ = 0; name##_ = name##__; } \
private:
#endif #endif
#include "ast.hpp"
namespace Sass {
#define IMPLEMENT_BASE_CAST(T) \
template<> \
T* Cast(AST_Node* ptr) { \
return dynamic_cast<T*>(ptr); \
}; \
\
template<> \
const T* Cast(const AST_Node* ptr) { \
return dynamic_cast<const T*>(ptr); \
}; \
IMPLEMENT_BASE_CAST(AST_Node)
IMPLEMENT_BASE_CAST(Expression)
IMPLEMENT_BASE_CAST(Statement)
IMPLEMENT_BASE_CAST(Has_Block)
IMPLEMENT_BASE_CAST(PreValue)
IMPLEMENT_BASE_CAST(Value)
IMPLEMENT_BASE_CAST(List)
IMPLEMENT_BASE_CAST(String)
IMPLEMENT_BASE_CAST(String_Constant)
IMPLEMENT_BASE_CAST(Supports_Condition)
IMPLEMENT_BASE_CAST(Selector)
IMPLEMENT_BASE_CAST(Simple_Selector)
}
#ifndef SASS_AST_FWD_DECL_H #ifndef SASS_AST_FWD_DECL_H
#define SASS_AST_FWD_DECL_H #define SASS_AST_FWD_DECL_H
#include <map>
#include <set>
#include <deque>
#include <vector> #include <vector>
#include <typeinfo>
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <unordered_map> #include <unordered_map>
...@@ -353,37 +357,94 @@ namespace Sass { ...@@ -353,37 +357,94 @@ namespace Sass {
IMPL_MEM_OBJ(Complex_Selector); IMPL_MEM_OBJ(Complex_Selector);
IMPL_MEM_OBJ(Selector_List); IMPL_MEM_OBJ(Selector_List);
// ###########################################################################
// Implement compare, order and hashing operations for AST Nodes
// ###########################################################################
struct HashExpression { struct HashNodes {
size_t operator() (Expression_Obj ex) const; template <class T>
size_t operator() (const T& ex) const {
return ex.isNull() ? 0 : ex->hash();
}
}; };
struct CompareExpression { struct OrderNodes {
bool operator()(const Expression_Obj& lhs, const Expression_Obj& rhs) const; template <class T>
bool operator() (const T& lhs, const T& rhs) const {
return !lhs.isNull() && !rhs.isNull() && *lhs < *rhs;
}
}; };
struct CompareNodes {
struct HashSimpleSelector { template <class T>
size_t operator() (Simple_Selector_Obj ex) const; bool operator() (const T& lhs, const T& rhs) const {
return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs;
}
}; };
struct CompareSimpleSelector { // ###########################################################################
bool operator()(Simple_Selector_Obj lhs, Simple_Selector_Obj rhs) const; // some often used typedefs
}; // ###########################################################################
typedef std::unordered_map< typedef std::unordered_map<
Expression_Obj, // key Expression_Obj, // key
Expression_Obj, // value Expression_Obj, // value
HashExpression, // hasher HashNodes, // hasher
CompareExpression // compare CompareNodes // compare
> ExpressionMap; > ExpressionMap;
typedef std::unordered_set< typedef std::unordered_set<
Expression_Obj, // value Expression_Obj, // value
HashExpression, // hasher HashNodes, // hasher
CompareExpression // compare CompareNodes // compare
> ExpressionSet; > ExpressionSet;
typedef std::string Subset_Map_Key; typedef std::string SubSetMapKey;
typedef std::vector<size_t> Subset_Map_Arr; typedef std::vector<std::string> SubSetMapKeys;
typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> Subset_Map_Val;
typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> SubSetMapPair;
typedef std::pair<Compound_Selector_Obj, Complex_Selector_Obj> SubSetMapLookup;
typedef std::vector<SubSetMapPair> SubSetMapPairs;
typedef std::vector<SubSetMapLookup> SubSetMapLookups;
typedef std::pair<Complex_Selector_Obj, SubSetMapPairs> SubSetMapResult;
typedef std::vector<SubSetMapResult> SubSetMapResults;
typedef std::deque<Complex_Selector_Obj> ComplexSelectorDeque;
typedef std::set<Simple_Selector_Obj, OrderNodes> SimpleSelectorSet;
typedef std::set<Complex_Selector_Obj, OrderNodes> ComplexSelectorSet;
typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict;
// ###########################################################################
// explicit type conversion functions
// ###########################################################################
template<class T>
T* Cast(AST_Node* ptr);
template<class T>
const T* Cast(const AST_Node* ptr);
// sometimes you know the class you want to cast to is final
// in this case a simple typeid check is faster and safe to use
#define DECLARE_BASE_CAST(T) \
template<> T* Cast(AST_Node* ptr); \
template<> const T* Cast(const AST_Node* ptr); \
// ###########################################################################
// implement specialization for final classes
// ###########################################################################
DECLARE_BASE_CAST(AST_Node)
DECLARE_BASE_CAST(Expression)
DECLARE_BASE_CAST(Statement)
DECLARE_BASE_CAST(Has_Block)
DECLARE_BASE_CAST(PreValue)
DECLARE_BASE_CAST(Value)
DECLARE_BASE_CAST(List)
DECLARE_BASE_CAST(String)
DECLARE_BASE_CAST(String_Constant)
DECLARE_BASE_CAST(Supports_Condition)
DECLARE_BASE_CAST(Selector)
DECLARE_BASE_CAST(Simple_Selector)
} }
......
...@@ -21,7 +21,7 @@ namespace Sass { ...@@ -21,7 +21,7 @@ namespace Sass {
caller(c) caller(c)
{ } { }
std::string to_string(bool warning = false) const std::string to_string(bool warning = false)
{ {
size_t i = -1; size_t i = -1;
std::stringstream ss; std::stringstream ss;
......
...@@ -16,7 +16,7 @@ namespace Sass { ...@@ -16,7 +16,7 @@ namespace Sass {
std::map<std::string, Parameter_Obj> param_map; std::map<std::string, Parameter_Obj> param_map;
for (size_t i = 0, L = as->length(); i < L; ++i) { for (size_t i = 0, L = as->length(); i < L; ++i) {
if (auto str = SASS_MEMORY_CAST(String_Quoted, (*as)[i]->value())) { if (auto str = Cast<String_Quoted>((*as)[i]->value())) {
// force optional quotes (only if needed) // force optional quotes (only if needed)
if (str->quote_mark()) { if (str->quote_mark()) {
str->quote_mark('*'); str->quote_mark('*');
...@@ -42,7 +42,7 @@ namespace Sass { ...@@ -42,7 +42,7 @@ namespace Sass {
if (ip >= LP) { if (ip >= LP) {
// skip empty rest arguments // skip empty rest arguments
if (a->is_rest_argument()) { if (a->is_rest_argument()) {
if (List_Obj l = SASS_MEMORY_CAST(List, a->value())) { if (List_Obj l = Cast<List>(a->value())) {
if (l->length() == 0) { if (l->length() == 0) {
++ ia; continue; ++ ia; continue;
} }
...@@ -61,7 +61,7 @@ namespace Sass { ...@@ -61,7 +61,7 @@ namespace Sass {
if (a->is_rest_argument()) { if (a->is_rest_argument()) {
// We should always get a list for rest arguments // We should always get a list for rest arguments
if (List_Obj rest = SASS_MEMORY_CAST(List, a->value())) { if (List_Obj rest = Cast<List>(a->value())) {
// create a new list object for wrapped items // create a new list object for wrapped items
List_Ptr arglist = SASS_MEMORY_NEW(List, List_Ptr arglist = SASS_MEMORY_NEW(List,
p->pstate(), p->pstate(),
...@@ -70,12 +70,12 @@ namespace Sass { ...@@ -70,12 +70,12 @@ namespace Sass {
true); true);
// wrap each item from list as an argument // wrap each item from list as an argument
for (Expression_Obj item : rest->elements()) { for (Expression_Obj item : rest->elements()) {
if (Argument_Obj arg = SASS_MEMORY_CAST(Argument, item)) { if (Argument_Obj arg = Cast<Argument>(item)) {
arglist->append(SASS_MEMORY_COPY(arg)); // copy arglist->append(SASS_MEMORY_COPY(arg)); // copy
} else { } else {
arglist->append(SASS_MEMORY_NEW(Argument, arglist->append(SASS_MEMORY_NEW(Argument,
item->pstate(), item->pstate(),
&item, item,
"", "",
false, false,
false)); false));
...@@ -93,9 +93,9 @@ namespace Sass { ...@@ -93,9 +93,9 @@ namespace Sass {
// expand keyword arguments into their parameters // expand keyword arguments into their parameters
List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true); List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true);
env->local_frame()[p->name()] = arglist; env->local_frame()[p->name()] = arglist;
Map_Obj argmap = SASS_MEMORY_CAST(Map, a->value()); Map_Obj argmap = Cast<Map>(a->value());
for (auto key : argmap->keys()) { for (auto key : argmap->keys()) {
std::string name = unquote(SASS_MEMORY_CAST(String_Constant, key)->value()); std::string name = unquote(Cast<String_Constant>(key)->value());
arglist->append(SASS_MEMORY_NEW(Argument, arglist->append(SASS_MEMORY_NEW(Argument,
key->pstate(), key->pstate(),
argmap->at(key), argmap->at(key),
...@@ -117,25 +117,25 @@ namespace Sass { ...@@ -117,25 +117,25 @@ namespace Sass {
// get and post inc // get and post inc
a = (*as)[ia++]; a = (*as)[ia++];
// maybe we have another list as argument // maybe we have another list as argument
List_Obj ls = SASS_MEMORY_CAST(List, a->value()); List_Obj ls = Cast<List>(a->value());
// skip any list completely if empty // skip any list completely if empty
if (ls && ls->empty() && a->is_rest_argument()) continue; if (ls && ls->empty() && a->is_rest_argument()) continue;
Expression_Obj value = a->value(); Expression_Obj value = a->value();
if (Argument_Obj arg = SASS_MEMORY_CAST(Argument, value)) { if (Argument_Obj arg = Cast<Argument>(value)) {
arglist->append(&arg); arglist->append(arg);
} }
// check if we have rest argument // check if we have rest argument
else if (a->is_rest_argument()) { else if (a->is_rest_argument()) {
// preserve the list separator from rest args // preserve the list separator from rest args
if (List_Obj rest = SASS_MEMORY_CAST(List, a->value())) { if (List_Obj rest = Cast<List>(a->value())) {
arglist->separator(rest->separator()); arglist->separator(rest->separator());
for (size_t i = 0, L = rest->size(); i < L; ++i) { for (size_t i = 0, L = rest->size(); i < L; ++i) {
Expression_Obj obj = rest->at(i); Expression_Obj obj = rest->at(i);
arglist->append(SASS_MEMORY_NEW(Argument, arglist->append(SASS_MEMORY_NEW(Argument,
obj->pstate(), obj->pstate(),
&obj, obj,
"", "",
false, false,
false)); false));
...@@ -155,7 +155,7 @@ namespace Sass { ...@@ -155,7 +155,7 @@ namespace Sass {
} }
} }
// assign new arglist to environment // assign new arglist to environment
env->local_frame()[p->name()] = &arglist; env->local_frame()[p->name()] = arglist;
} }
// consumed parameter // consumed parameter
++ip; ++ip;
...@@ -166,7 +166,7 @@ namespace Sass { ...@@ -166,7 +166,7 @@ namespace Sass {
// If the current argument is the rest argument, extract a value for processing // If the current argument is the rest argument, extract a value for processing
else if (a->is_rest_argument()) { else if (a->is_rest_argument()) {
// normal param and rest arg // normal param and rest arg
List_Obj arglist = SASS_MEMORY_CAST(List, a->value()); List_Obj arglist = Cast<List>(a->value());
// empty rest arg - treat all args as default values // empty rest arg - treat all args as default values
if (!arglist->length()) { if (!arglist->length()) {
break; break;
...@@ -187,8 +187,8 @@ namespace Sass { ...@@ -187,8 +187,8 @@ namespace Sass {
} }
// otherwise move one of the rest args into the param, converting to argument if necessary // otherwise move one of the rest args into the param, converting to argument if necessary
Expression_Obj obj = arglist->at(0); Expression_Obj obj = arglist->at(0);
if (!(a = SASS_MEMORY_CAST(Argument, obj))) { if (!(a = Cast<Argument>(obj))) {
Expression_Ptr a_to_convert = &obj; Expression_Ptr a_to_convert = obj;
a = SASS_MEMORY_NEW(Argument, a = SASS_MEMORY_NEW(Argument,
a_to_convert->pstate(), a_to_convert->pstate(),
a_to_convert, a_to_convert,
...@@ -202,17 +202,17 @@ namespace Sass { ...@@ -202,17 +202,17 @@ namespace Sass {
} }
} else if (a->is_keyword_argument()) { } else if (a->is_keyword_argument()) {
Map_Obj argmap = SASS_MEMORY_CAST(Map, a->value()); Map_Obj argmap = Cast<Map>(a->value());
for (auto key : argmap->keys()) { for (auto key : argmap->keys()) {
std::string name = "$" + unquote(SASS_MEMORY_CAST(String_Constant, key)->value()); std::string name = "$" + unquote(Cast<String_Constant>(key)->value());
if (!param_map.count(name)) { if (!param_map.count(name)) {
std::stringstream msg; std::stringstream msg;
msg << callee << " has no parameter named " << name; msg << callee << " has no parameter named " << name;
error(msg.str(), a->pstate()); error(msg.str(), a->pstate());
} }
env->local_frame()[name] = &argmap->at(&key); env->local_frame()[name] = argmap->at(key);
} }
++ia; ++ia;
continue; continue;
...@@ -228,7 +228,7 @@ namespace Sass { ...@@ -228,7 +228,7 @@ namespace Sass {
error(msg.str(), a->pstate()); error(msg.str(), a->pstate());
} }
// ordinal arg -- bind it to the next param // ordinal arg -- bind it to the next param
env->local_frame()[p->name()] = &a->value(); env->local_frame()[p->name()] = a->value();
++ip; ++ip;
} }
else { else {
...@@ -250,7 +250,7 @@ namespace Sass { ...@@ -250,7 +250,7 @@ namespace Sass {
<< "provided more than once in call to " << callee; << "provided more than once in call to " << callee;
error(msg.str(), a->pstate()); error(msg.str(), a->pstate());
} }
env->local_frame()[a->name()] = &a->value(); env->local_frame()[a->name()] = a->value();
} }
} }
// EO while ia // EO while ia
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "ast_fwd_decl.hpp" #include "ast_fwd_decl.hpp"
namespace Sass { namespace Sass {
typedef Environment<AST_Node_Obj> Env;
void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Context*, Env*, Eval*); void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Context*, Env*, Eval*);
} }
......
...@@ -15,7 +15,7 @@ namespace Sass { ...@@ -15,7 +15,7 @@ namespace Sass {
{ {
Statement_Ptr old_parent = this->parent; Statement_Ptr old_parent = this->parent;
if (At_Root_Block_Ptr root = SASS_MEMORY_CAST_PTR(At_Root_Block, parent)) { if (At_Root_Block_Ptr root = Cast<At_Root_Block>(parent)) {
std::vector<Statement_Ptr> old_parents = this->parents; std::vector<Statement_Ptr> old_parents = this->parents;
std::vector<Statement_Ptr> new_parents; std::vector<Statement_Ptr> new_parents;
...@@ -39,8 +39,8 @@ namespace Sass { ...@@ -39,8 +39,8 @@ namespace Sass {
} }
} }
At_Root_Block_Ptr ar = SASS_MEMORY_CAST_PTR(At_Root_Block, parent); At_Root_Block_Ptr ar = Cast<At_Root_Block>(parent);
Statement_Ptr ret = this->visit_children(&ar->block()); Statement_Ptr ret = this->visit_children(ar->block());
this->parent = old_parent; this->parent = old_parent;
this->parents = old_parents; this->parents = old_parents;
...@@ -54,11 +54,11 @@ namespace Sass { ...@@ -54,11 +54,11 @@ namespace Sass {
this->parents.push_back(parent); this->parents.push_back(parent);
Block_Ptr b = SASS_MEMORY_CAST_PTR(Block, parent); Block_Ptr b = Cast<Block>(parent);
if (!b) { if (!b) {
if (Has_Block_Ptr bb = SASS_MEMORY_CAST(Has_Block, *parent)) { if (Has_Block_Ptr bb = Cast<Has_Block>(parent)) {
b = &bb->block(); b = bb->block();
} }
} }
...@@ -99,8 +99,8 @@ namespace Sass { ...@@ -99,8 +99,8 @@ namespace Sass {
Statement_Ptr CheckNesting::fallback_impl(Statement_Ptr s) Statement_Ptr CheckNesting::fallback_impl(Statement_Ptr s)
{ {
Block_Ptr b1 = SASS_MEMORY_CAST_PTR(Block, s); Block_Ptr b1 = Cast<Block>(s);
Has_Block_Ptr b2 = SASS_MEMORY_CAST_PTR(Has_Block, s); Has_Block_Ptr b2 = Cast<Has_Block>(s);
return b1 || b2 ? visit_children(s) : s; return b1 || b2 ? visit_children(s) : s;
} }
...@@ -108,16 +108,16 @@ namespace Sass { ...@@ -108,16 +108,16 @@ namespace Sass {
{ {
if (!this->parent) return true; if (!this->parent) return true;
if (SASS_MEMORY_CAST_PTR(Content, node)) if (Cast<Content>(node))
{ this->invalid_content_parent(this->parent); } { this->invalid_content_parent(this->parent); }
if (is_charset(node)) if (is_charset(node))
{ this->invalid_charset_parent(this->parent); } { this->invalid_charset_parent(this->parent); }
if (SASS_MEMORY_CAST_PTR(Extension, node)) if (Cast<Extension>(node))
{ this->invalid_extend_parent(this->parent); } { this->invalid_extend_parent(this->parent); }
// if (SASS_MEMORY_CAST(Import, node)) // if (Cast<Import>(node))
// { this->invalid_import_parent(this->parent); } // { this->invalid_import_parent(this->parent); }
if (this->is_mixin(node)) if (this->is_mixin(node))
...@@ -129,13 +129,13 @@ namespace Sass { ...@@ -129,13 +129,13 @@ namespace Sass {
if (this->is_function(this->parent)) if (this->is_function(this->parent))
{ this->invalid_function_child(node); } { this->invalid_function_child(node); }
if (SASS_MEMORY_CAST_PTR(Declaration, node)) if (Cast<Declaration>(node))
{ this->invalid_prop_parent(this->parent); } { this->invalid_prop_parent(this->parent); }
if (SASS_MEMORY_CAST_PTR(Declaration, this->parent)) if (Cast<Declaration>(this->parent))
{ this->invalid_prop_child(node); } { this->invalid_prop_child(node); }
if (SASS_MEMORY_CAST_PTR(Return, node)) if (Cast<Return>(node))
{ this->invalid_return_parent(this->parent); } { this->invalid_return_parent(this->parent); }
return true; return true;
...@@ -166,8 +166,8 @@ namespace Sass { ...@@ -166,8 +166,8 @@ namespace Sass {
void CheckNesting::invalid_extend_parent(Statement_Ptr parent) void CheckNesting::invalid_extend_parent(Statement_Ptr parent)
{ {
if (!( if (!(
SASS_MEMORY_CAST_PTR(Ruleset, parent) || Cast<Ruleset>(parent) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, parent) || Cast<Mixin_Call>(parent) ||
is_mixin(parent) is_mixin(parent)
)) { )) {
throw Exception::InvalidSass( throw Exception::InvalidSass(
...@@ -181,12 +181,12 @@ namespace Sass { ...@@ -181,12 +181,12 @@ namespace Sass {
// { // {
// for (auto pp : this->parents) { // for (auto pp : this->parents) {
// if ( // if (
// SASS_MEMORY_CAST(Each, pp) || // Cast<Each>(pp) ||
// SASS_MEMORY_CAST(For, pp) || // Cast<For>(pp) ||
// SASS_MEMORY_CAST(If, pp) || // Cast<If>(pp) ||
// SASS_MEMORY_CAST(While, pp) || // Cast<While>(pp) ||
// SASS_MEMORY_CAST(Trace, pp) || // Cast<Trace>(pp) ||
// SASS_MEMORY_CAST(Mixin_Call, pp) || // Cast<Mixin_Call>(pp) ||
// is_mixin(pp) // is_mixin(pp)
// ) { // ) {
// throw Exception::InvalidSass( // throw Exception::InvalidSass(
...@@ -212,12 +212,12 @@ namespace Sass { ...@@ -212,12 +212,12 @@ namespace Sass {
{ {
for (Statement_Ptr pp : this->parents) { for (Statement_Ptr pp : this->parents) {
if ( if (
SASS_MEMORY_CAST_PTR(Each, pp) || Cast<Each>(pp) ||
SASS_MEMORY_CAST_PTR(For, pp) || Cast<For>(pp) ||
SASS_MEMORY_CAST_PTR(If, pp) || Cast<If>(pp) ||
SASS_MEMORY_CAST_PTR(While, pp) || Cast<While>(pp) ||
SASS_MEMORY_CAST_PTR(Trace, pp) || Cast<Trace>(pp) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, pp) || Cast<Mixin_Call>(pp) ||
is_mixin(pp) is_mixin(pp)
) { ) {
throw Exception::InvalidSass( throw Exception::InvalidSass(
...@@ -232,12 +232,12 @@ namespace Sass { ...@@ -232,12 +232,12 @@ namespace Sass {
{ {
for (Statement_Ptr pp : this->parents) { for (Statement_Ptr pp : this->parents) {
if ( if (
SASS_MEMORY_CAST_PTR(Each, pp) || Cast<Each>(pp) ||
SASS_MEMORY_CAST_PTR(For, pp) || Cast<For>(pp) ||
SASS_MEMORY_CAST_PTR(If, pp) || Cast<If>(pp) ||
SASS_MEMORY_CAST_PTR(While, pp) || Cast<While>(pp) ||
SASS_MEMORY_CAST_PTR(Trace, pp) || Cast<Trace>(pp) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, pp) || Cast<Mixin_Call>(pp) ||
is_mixin(pp) is_mixin(pp)
) { ) {
throw Exception::InvalidSass( throw Exception::InvalidSass(
...@@ -251,19 +251,19 @@ namespace Sass { ...@@ -251,19 +251,19 @@ namespace Sass {
void CheckNesting::invalid_function_child(Statement_Ptr child) void CheckNesting::invalid_function_child(Statement_Ptr child)
{ {
if (!( if (!(
SASS_MEMORY_CAST_PTR(Each, child) || Cast<Each>(child) ||
SASS_MEMORY_CAST_PTR(For, child) || Cast<For>(child) ||
SASS_MEMORY_CAST_PTR(If, child) || Cast<If>(child) ||
SASS_MEMORY_CAST_PTR(While, child) || Cast<While>(child) ||
SASS_MEMORY_CAST_PTR(Trace, child) || Cast<Trace>(child) ||
SASS_MEMORY_CAST_PTR(Comment, child) || Cast<Comment>(child) ||
SASS_MEMORY_CAST_PTR(Debug, child) || Cast<Debug>(child) ||
SASS_MEMORY_CAST_PTR(Return, child) || Cast<Return>(child) ||
SASS_MEMORY_CAST_PTR(Variable, child) || Cast<Variable>(child) ||
// Ruby Sass doesn't distinguish variables and assignments // Ruby Sass doesn't distinguish variables and assignments
SASS_MEMORY_CAST_PTR(Assignment, child) || Cast<Assignment>(child) ||
SASS_MEMORY_CAST_PTR(Warning, child) || Cast<Warning>(child) ||
SASS_MEMORY_CAST_PTR(Error, child) Cast<Error>(child)
)) { )) {
throw Exception::InvalidSass( throw Exception::InvalidSass(
child->pstate(), child->pstate(),
...@@ -275,14 +275,14 @@ namespace Sass { ...@@ -275,14 +275,14 @@ namespace Sass {
void CheckNesting::invalid_prop_child(Statement_Ptr child) void CheckNesting::invalid_prop_child(Statement_Ptr child)
{ {
if (!( if (!(
SASS_MEMORY_CAST_PTR(Each, child) || Cast<Each>(child) ||
SASS_MEMORY_CAST_PTR(For, child) || Cast<For>(child) ||
SASS_MEMORY_CAST_PTR(If, child) || Cast<If>(child) ||
SASS_MEMORY_CAST_PTR(While, child) || Cast<While>(child) ||
SASS_MEMORY_CAST_PTR(Trace, child) || Cast<Trace>(child) ||
SASS_MEMORY_CAST_PTR(Comment, child) || Cast<Comment>(child) ||
SASS_MEMORY_CAST_PTR(Declaration, child) || Cast<Declaration>(child) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, child) Cast<Mixin_Call>(child)
)) { )) {
throw Exception::InvalidSass( throw Exception::InvalidSass(
child->pstate(), child->pstate(),
...@@ -296,10 +296,10 @@ namespace Sass { ...@@ -296,10 +296,10 @@ namespace Sass {
if (!( if (!(
is_mixin(parent) || is_mixin(parent) ||
is_directive_node(parent) || is_directive_node(parent) ||
SASS_MEMORY_CAST_PTR(Ruleset, parent) || Cast<Ruleset>(parent) ||
SASS_MEMORY_CAST_PTR(Keyframe_Rule, parent) || Cast<Keyframe_Rule>(parent) ||
SASS_MEMORY_CAST_PTR(Declaration, parent) || Cast<Declaration>(parent) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, parent) Cast<Mixin_Call>(parent)
)) { )) {
throw Exception::InvalidSass( throw Exception::InvalidSass(
parent->pstate(), parent->pstate(),
...@@ -326,51 +326,51 @@ namespace Sass { ...@@ -326,51 +326,51 @@ namespace Sass {
!is_root_node(grandparent) && !is_root_node(grandparent) &&
!is_at_root_node(grandparent); !is_at_root_node(grandparent);
return SASS_MEMORY_CAST_PTR(Import, parent) || return Cast<Import>(parent) ||
SASS_MEMORY_CAST_PTR(Each, parent) || Cast<Each>(parent) ||
SASS_MEMORY_CAST_PTR(For, parent) || Cast<For>(parent) ||
SASS_MEMORY_CAST_PTR(If, parent) || Cast<If>(parent) ||
SASS_MEMORY_CAST_PTR(While, parent) || Cast<While>(parent) ||
SASS_MEMORY_CAST_PTR(Trace, parent) || Cast<Trace>(parent) ||
valid_bubble_node; valid_bubble_node;
} }
bool CheckNesting::is_charset(Statement_Ptr n) bool CheckNesting::is_charset(Statement_Ptr n)
{ {
Directive_Ptr d = SASS_MEMORY_CAST_PTR(Directive, n); Directive_Ptr d = Cast<Directive>(n);
return d && d->keyword() == "charset"; return d && d->keyword() == "charset";
} }
bool CheckNesting::is_mixin(Statement_Ptr n) bool CheckNesting::is_mixin(Statement_Ptr n)
{ {
Definition_Ptr def = SASS_MEMORY_CAST_PTR(Definition, n); Definition_Ptr def = Cast<Definition>(n);
return def && def->type() == Definition::MIXIN; return def && def->type() == Definition::MIXIN;
} }
bool CheckNesting::is_function(Statement_Ptr n) bool CheckNesting::is_function(Statement_Ptr n)
{ {
Definition_Ptr def = SASS_MEMORY_CAST_PTR(Definition, n); Definition_Ptr def = Cast<Definition>(n);
return def && def->type() == Definition::FUNCTION; return def && def->type() == Definition::FUNCTION;
} }
bool CheckNesting::is_root_node(Statement_Ptr n) bool CheckNesting::is_root_node(Statement_Ptr n)
{ {
if (SASS_MEMORY_CAST_PTR(Ruleset, n)) return false; if (Cast<Ruleset>(n)) return false;
Block_Ptr b = SASS_MEMORY_CAST_PTR(Block, n); Block_Ptr b = Cast<Block>(n);
return b && b->is_root(); return b && b->is_root();
} }
bool CheckNesting::is_at_root_node(Statement_Ptr n) bool CheckNesting::is_at_root_node(Statement_Ptr n)
{ {
return SASS_MEMORY_CAST_PTR(At_Root_Block, n) != NULL; return Cast<At_Root_Block>(n) != NULL;
} }
bool CheckNesting::is_directive_node(Statement_Ptr n) bool CheckNesting::is_directive_node(Statement_Ptr n)
{ {
return SASS_MEMORY_CAST_PTR(Directive, n) || return Cast<Directive>(n) ||
SASS_MEMORY_CAST_PTR(Import, n) || Cast<Import>(n) ||
SASS_MEMORY_CAST_PTR(Media_Block, n) || Cast<Media_Block>(n) ||
SASS_MEMORY_CAST_PTR(Supports_Block, n); Cast<Supports_Block>(n);
} }
} }
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
namespace Sass { namespace Sass {
typedef Environment<AST_Node_Obj> Env;
class CheckNesting : public Operation_CRTP<Statement_Ptr, CheckNesting> { class CheckNesting : public Operation_CRTP<Statement_Ptr, CheckNesting> {
std::vector<Statement_Ptr> parents; std::vector<Statement_Ptr> parents;
...@@ -27,7 +25,7 @@ namespace Sass { ...@@ -27,7 +25,7 @@ namespace Sass {
template <typename U> template <typename U>
Statement_Ptr fallback(U x) { Statement_Ptr fallback(U x) {
Statement_Ptr n = SASS_MEMORY_CAST_PTR(Statement, x); Statement_Ptr n = Cast<Statement>(x);
if (this->should_visit(n)) { if (this->should_visit(n)) {
return fallback_impl(n); return fallback_impl(n);
} }
......
#ifndef SASS_COLOR_MAPS_H #ifndef SASS_COLOR_MAPS_H
#define SASS_COLOR_MAPS_H #define SASS_COLOR_MAPS_H
...@@ -319,14 +320,11 @@ namespace Sass { ...@@ -319,14 +320,11 @@ namespace Sass {
extern const Color transparent; extern const Color transparent;
} }
extern const std::map<const int, const char*> colors_to_names; Color_Ptr_Const name_to_color(const char*);
extern const std::map<const char*, Color_Ptr_Const, map_cmp_str> names_to_colors; Color_Ptr_Const name_to_color(const std::string&);
const char* color_to_name(const int);
extern Color_Ptr_Const name_to_color(const char*); const char* color_to_name(const Color&);
extern Color_Ptr_Const name_to_color(const std::string&); const char* color_to_name(const double);
extern const char* color_to_name(const int);
extern const char* color_to_name(const Color&);
extern const char* color_to_name(const double);
} }
......
...@@ -87,8 +87,9 @@ namespace Sass { ...@@ -87,8 +87,9 @@ namespace Sass {
{ {
// add cwd to include paths // Sass 3.4: The current working directory will no longer be placed onto the Sass load path by default.
include_paths.push_back(CWD); // If you need the current working directory to be available, set SASS_PATH=. in your shell's environment.
// include_paths.push_back(CWD);
// collect more paths from different options // collect more paths from different options
collect_include_paths(c_options.include_path); collect_include_paths(c_options.include_path);
...@@ -391,8 +392,8 @@ namespace Sass { ...@@ -391,8 +392,8 @@ namespace Sass {
String_Constant_Ptr loc = SASS_MEMORY_NEW(String_Constant, pstate, unquote(load_path)); String_Constant_Ptr loc = SASS_MEMORY_NEW(String_Constant, pstate, unquote(load_path));
Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc); Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc);
Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate); Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate);
loc_args->append(&loc_arg); loc_args->append(loc_arg);
Function_Call_Ptr new_url = SASS_MEMORY_NEW(Function_Call, pstate, "url", &loc_args); Function_Call_Ptr new_url = SASS_MEMORY_NEW(Function_Call, pstate, "url", loc_args);
imp->urls().push_back(new_url); imp->urls().push_back(new_url);
} }
else { else {
...@@ -528,11 +529,11 @@ namespace Sass { ...@@ -528,11 +529,11 @@ namespace Sass {
Import_Obj imp = SASS_MEMORY_NEW(Import, pstate); Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
// dispatch headers which will add custom functions // dispatch headers which will add custom functions
// custom headers are added to the import instance // custom headers are added to the import instance
call_headers(entry_path, ctx_path, pstate, &imp); call_headers(entry_path, ctx_path, pstate, imp);
// increase head count to skip later // increase head count to skip later
head_imports += resources.size() - 1; head_imports += resources.size() - 1;
// add the statement if we have urls // add the statement if we have urls
if (!imp->urls().empty()) root->append(&imp); if (!imp->urls().empty()) root->append(imp);
// process all other resources (add Import_Stub nodes) // process all other resources (add Import_Stub nodes)
for (size_t i = 0, S = imp->incs().size(); i < S; ++i) { for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
root->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i])); root->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i]));
...@@ -650,24 +651,24 @@ namespace Sass { ...@@ -650,24 +651,24 @@ namespace Sass {
Cssize cssize(*this, &backtrace); Cssize cssize(*this, &backtrace);
CheckNesting check_nesting; CheckNesting check_nesting;
// check nesting // check nesting
check_nesting(&root); check_nesting(root);
// expand and eval the tree // expand and eval the tree
root = expand(&root); root = expand(root);
// check nesting // check nesting
check_nesting(&root); check_nesting(root);
// merge and bubble certain rules // merge and bubble certain rules
root = cssize(&root); root = cssize(root);
// should we extend something? // should we extend something?
if (!subset_map.empty()) { if (!subset_map.empty()) {
// create crtp visitor object // create crtp visitor object
Extend extend(*this, subset_map); Extend extend(*this, subset_map);
// extend tree nodes // extend tree nodes
extend(&root); extend(root);
} }
// clean up by removing empty placeholders // clean up by removing empty placeholders
// ToDo: maybe we can do this somewhere else? // ToDo: maybe we can do this somewhere else?
Remove_Placeholders remove_placeholders(*this); Remove_Placeholders remove_placeholders;
root->perform(&remove_placeholders); root->perform(&remove_placeholders);
// return processed tree // return processed tree
return root; return root;
...@@ -810,6 +811,7 @@ namespace Sass { ...@@ -810,6 +811,7 @@ namespace Sass {
register_function(ctx, append_sig, append, env); register_function(ctx, append_sig, append, env);
register_function(ctx, zip_sig, zip, env); register_function(ctx, zip_sig, zip, env);
register_function(ctx, list_separator_sig, list_separator, env); register_function(ctx, list_separator_sig, list_separator, env);
register_function(ctx, is_bracketed_sig, is_bracketed, env);
// Map Functions // Map Functions
register_function(ctx, map_get_sig, map_get, env); register_function(ctx, map_get_sig, map_get, env);
register_function(ctx, map_merge_sig, map_merge, env); register_function(ctx, map_merge_sig, map_merge, env);
......
...@@ -50,6 +50,7 @@ namespace Sass { ...@@ -50,6 +50,7 @@ namespace Sass {
std::map<const std::string, StyleSheet> sheets; std::map<const std::string, StyleSheet> sheets;
Subset_Map subset_map; Subset_Map subset_map;
std::vector<Sass_Import_Entry> import_stack; std::vector<Sass_Import_Entry> import_stack;
std::vector<Sass_Callee> callee_stack;
struct Sass_Compiler* c_compiler; struct Sass_Compiler* c_compiler;
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
namespace Sass { namespace Sass {
typedef Environment<AST_Node_Obj> Env;
struct Backtrace; struct Backtrace;
class Cssize : public Operation_CRTP<Statement_Ptr, Cssize> { class Cssize : public Operation_CRTP<Statement_Ptr, Cssize> {
......
...@@ -179,7 +179,7 @@ namespace Sass { ...@@ -179,7 +179,7 @@ namespace Sass {
for (typename std::map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) { for (typename std::map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) { if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second; std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
if (Value_Ptr val = SASS_MEMORY_CAST_PTR(Value, i->second)) if (Value_Ptr val = Cast<Value>(i->second))
{ std::cerr << " : " << val->to_string(); } { std::cerr << " : " << val->to_string(); }
std::cerr << std::endl; std::cerr << std::endl;
} }
......
...@@ -87,6 +87,9 @@ namespace Sass { ...@@ -87,6 +87,9 @@ namespace Sass {
}; };
// define typedef for our use case
typedef Environment<AST_Node_Obj> Env;
} }
#endif #endif
...@@ -13,14 +13,12 @@ namespace Sass { ...@@ -13,14 +13,12 @@ namespace Sass {
class Listize; class Listize;
class Context; class Context;
class Eval; class Eval;
typedef Environment<AST_Node_Obj> Env;
struct Backtrace; struct Backtrace;
class Expand : public Operation_CRTP<Statement_Ptr, Expand> { class Expand : public Operation_CRTP<Statement_Ptr, Expand> {
public: public:
Env* environment(); Env* environment();
Context& context();
Selector_List_Obj selector(); Selector_List_Obj selector();
Backtrace* backtrace(); Backtrace* backtrace();
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "context.hpp" #include "context.hpp"
#include "prelexer.hpp" #include "prelexer.hpp"
#include "utf8_string.hpp" #include "utf8_string.hpp"
#include "sass_functions.hpp"
#include "sass2scss.h" #include "sass2scss.h"
#ifdef _WIN32 #ifdef _WIN32
...@@ -301,13 +302,9 @@ namespace Sass { ...@@ -301,13 +302,9 @@ namespace Sass {
// (2) underscore + given // (2) underscore + given
// (3) underscore + given + extension // (3) underscore + given + extension
// (4) given + extension // (4) given + extension
std::vector<Include> resolve_includes(const std::string& root, const std::string& file) std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
{ {
std::string filename = join_paths(root, file); std::string filename = join_paths(root, file);
// supported extensions
const std::vector<std::string> exts = {
".scss", ".sass", ".css"
};
// split the filename // split the filename
std::string base(dir_name(file)); std::string base(dir_name(file));
std::string name(base_name(file)); std::string name(base_name(file));
...@@ -336,9 +333,42 @@ namespace Sass { ...@@ -336,9 +333,42 @@ namespace Sass {
return includes; return includes;
} }
// helper function to resolve a filename std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
{
std::vector<std::string> includes;
for (std::string path : paths) {
std::string abs_path(join_paths(path, file));
if (file_exists(abs_path)) includes.push_back(abs_path);
}
return includes;
}
std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
{
// get the last import entry to get current base directory
// struct Sass_Options* options = sass_compiler_get_options(compiler);
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
// create the vector with paths to lookup
std::vector<std::string> paths(1 + incs.size());
paths.push_back(dir_name(import->abs_path));
paths.insert(paths.end(), incs.begin(), incs.end());
// dispatch to find files in paths
return find_files(file, paths);
}
// helper function to search one file in all include paths
// this is normally not used internally by libsass (C-API sugar)
std::string find_file(const std::string& file, const std::vector<std::string> paths) std::string find_file(const std::string& file, const std::vector<std::string> paths)
{ {
if (file.empty()) return file;
auto res = find_files(file, paths);
return res.empty() ? "" : res.front();
}
// helper function to resolve a filename
std::string find_include(const std::string& file, const std::vector<std::string> paths)
{
// search in every include path for a match // search in every include path for a match
for (size_t i = 0, S = paths.size(); i < S; ++i) for (size_t i = 0, S = paths.size(); i < S; ++i)
{ {
...@@ -349,20 +379,6 @@ namespace Sass { ...@@ -349,20 +379,6 @@ namespace Sass {
return std::string(""); return std::string("");
} }
// inc paths can be directly passed from C code
std::string find_file(const std::string& file, const char* paths[])
{
if (paths == 0) return std::string("");
std::vector<std::string> includes(0);
// includes.push_back(".");
const char** it = paths;
while (it && *it) {
includes.push_back(*it);
++it;
}
return find_file(file, includes);
}
// try to load the given filename // try to load the given filename
// returned memory must be freed // returned memory must be freed
// will auto convert .sass files // will auto convert .sass files
...@@ -414,5 +430,25 @@ namespace Sass { ...@@ -414,5 +430,25 @@ namespace Sass {
} }
} }
// split a path string delimited by semicolons or colons (OS dependent)
std::vector<std::string> split_path_list(const char* str)
{
std::vector<std::string> paths;
if (str == NULL) return paths;
// find delimiter via prelexer (return zero at end)
const char* end = Prelexer::find_first<PATH_SEP>(str);
// search until null delimiter
while (end) {
// add path from current position to delimiter
paths.push_back(std::string(str, end - str));
str = end + 1; // skip delimiter
end = Prelexer::find_first<PATH_SEP>(str);
}
// add path from current position to end
paths.push_back(std::string(str));
// return back
return paths;
}
} }
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "sass/context.h"
#include "ast_fwd_decl.hpp" #include "ast_fwd_decl.hpp"
namespace Sass { namespace Sass {
...@@ -47,9 +48,16 @@ namespace Sass { ...@@ -47,9 +48,16 @@ namespace Sass {
std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd()); std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd());
// helper function to resolve a filename // helper function to resolve a filename
// searching without variations in all paths
std::string find_file(const std::string& file, struct Sass_Compiler* options);
std::string find_file(const std::string& file, const std::vector<std::string> paths); std::string find_file(const std::string& file, const std::vector<std::string> paths);
// inc paths can be directly passed from C code
std::string find_file(const std::string& file, const char** paths); // helper function to resolve a include filename
// this has the original resolve logic for sass include
std::string find_include(const std::string& file, const std::vector<std::string> paths);
// split a path string delimited by semicolons or colons (OS dependent)
std::vector<std::string> split_path_list(const char* paths);
// try to load the given filename // try to load the given filename
// returned memory must be freed // returned memory must be freed
...@@ -113,7 +121,10 @@ namespace Sass { ...@@ -113,7 +121,10 @@ namespace Sass {
namespace File { namespace File {
std::vector<Include> resolve_includes(const std::string& root, const std::string& file); static std::vector<std::string> defaultExtensions = { ".scss", ".sass", ".css" };
std::vector<Include> resolve_includes(const std::string& root, const std::string& file,
const std::vector<std::string>& exts = defaultExtensions);
} }
......
...@@ -12,7 +12,6 @@ name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Back ...@@ -12,7 +12,6 @@ name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Back
namespace Sass { namespace Sass {
struct Backtrace; struct Backtrace;
typedef Environment<AST_Node_Obj> Env;
typedef const char* Signature; typedef const char* Signature;
typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector<Selector_List_Obj>); typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector<Selector_List_Obj>);
...@@ -89,7 +88,6 @@ namespace Sass { ...@@ -89,7 +88,6 @@ namespace Sass {
extern Signature call_sig; extern Signature call_sig;
extern Signature not_sig; extern Signature not_sig;
extern Signature if_sig; extern Signature if_sig;
extern Signature image_url_sig;
extern Signature map_get_sig; extern Signature map_get_sig;
extern Signature map_merge_sig; extern Signature map_merge_sig;
extern Signature map_remove_sig; extern Signature map_remove_sig;
...@@ -107,6 +105,7 @@ namespace Sass { ...@@ -107,6 +105,7 @@ namespace Sass {
extern Signature is_superselector_sig; extern Signature is_superselector_sig;
extern Signature simple_selectors_sig; extern Signature simple_selectors_sig;
extern Signature selector_parse_sig; extern Signature selector_parse_sig;
extern Signature is_bracketed_sig;
BUILT_IN(rgb); BUILT_IN(rgb);
BUILT_IN(rgba_4); BUILT_IN(rgba_4);
...@@ -171,7 +170,6 @@ namespace Sass { ...@@ -171,7 +170,6 @@ namespace Sass {
BUILT_IN(call); BUILT_IN(call);
BUILT_IN(sass_not); BUILT_IN(sass_not);
BUILT_IN(sass_if); BUILT_IN(sass_if);
BUILT_IN(image_url);
BUILT_IN(map_get); BUILT_IN(map_get);
BUILT_IN(map_merge); BUILT_IN(map_merge);
BUILT_IN(map_remove); BUILT_IN(map_remove);
...@@ -189,6 +187,7 @@ namespace Sass { ...@@ -189,6 +187,7 @@ namespace Sass {
BUILT_IN(is_superselector); BUILT_IN(is_superselector);
BUILT_IN(simple_selectors); BUILT_IN(simple_selectors);
BUILT_IN(selector_parse); BUILT_IN(selector_parse);
BUILT_IN(is_bracketed);
} }
} }
......
...@@ -166,7 +166,7 @@ namespace Sass { ...@@ -166,7 +166,7 @@ namespace Sass {
import->urls().front()->perform(this); import->urls().front()->perform(this);
if (import->urls().size() == 1) { if (import->urls().size() == 1) {
if (&import->import_queries()) { if (import->import_queries()) {
append_mandatory_space(); append_mandatory_space();
import->import_queries()->perform(this); import->import_queries()->perform(this);
} }
...@@ -179,7 +179,7 @@ namespace Sass { ...@@ -179,7 +179,7 @@ namespace Sass {
import->urls()[i]->perform(this); import->urls()[i]->perform(this);
if (import->urls().size() - 1 == i) { if (import->urls().size() - 1 == i) {
if (&import->import_queries()) { if (import->import_queries()) {
append_mandatory_space(); append_mandatory_space();
import->import_queries()->perform(this); import->import_queries()->perform(this);
} }
...@@ -360,10 +360,19 @@ namespace Sass { ...@@ -360,10 +360,19 @@ namespace Sass {
append_string(")"); append_string(")");
} }
std::string Inspect::lbracket(List_Ptr list) {
return list->is_bracketed() ? "[" : "(";
}
std::string Inspect::rbracket(List_Ptr list) {
return list->is_bracketed() ? "]" : ")";
}
void Inspect::operator()(List_Ptr list) void Inspect::operator()(List_Ptr list)
{ {
if (output_style() == TO_SASS && list->empty()) { if (list->empty() && (output_style() == TO_SASS || list->is_bracketed())) {
append_string("()"); append_string(lbracket(list));
append_string(rbracket(list));
return; return;
} }
std::string sep(list->separator() == SASS_SPACE ? " " : ","); std::string sep(list->separator() == SASS_SPACE ? " " : ",");
...@@ -374,19 +383,24 @@ namespace Sass { ...@@ -374,19 +383,24 @@ namespace Sass {
bool was_space_array = in_space_array; bool was_space_array = in_space_array;
bool was_comma_array = in_comma_array; bool was_comma_array = in_comma_array;
// if the list is bracketed, always include the left bracket
if (list->is_bracketed()) {
append_string(lbracket(list));
}
// probably ruby sass eqivalent of element_needs_parens // probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS && else if (output_style() == TO_SASS &&
list->length() == 1 && list->length() == 1 &&
!list->from_selector() && !list->from_selector() &&
!SASS_MEMORY_CAST(List, list->at(0)) && !Cast<List>(list->at(0)) &&
!SASS_MEMORY_CAST(Selector_List, list->at(0))) { !Cast<Selector_List>(list->at(0))
append_string("("); ) {
append_string(lbracket(list));
} }
else if (!in_declaration && (list->separator() == SASS_HASH || else if (!in_declaration && (list->separator() == SASS_HASH ||
(list->separator() == SASS_SPACE && in_space_array) || (list->separator() == SASS_SPACE && in_space_array) ||
(list->separator() == SASS_COMMA && in_comma_array) (list->separator() == SASS_COMMA && in_comma_array)
)) { )) {
append_string("("); append_string(lbracket(list));
} }
if (list->separator() == SASS_SPACE) in_space_array = true; if (list->separator() == SASS_SPACE) in_space_array = true;
...@@ -399,7 +413,7 @@ namespace Sass { ...@@ -399,7 +413,7 @@ namespace Sass {
if (output_style() != TO_SASS) { if (output_style() != TO_SASS) {
if (list_item->is_invisible()) { if (list_item->is_invisible()) {
// this fixes an issue with "" in a list // this fixes an issue with "" in a list
if (!SASS_MEMORY_CAST(String_Constant, list_item)) { if (!Cast<String_Constant>(list_item)) {
continue; continue;
} }
} }
...@@ -415,19 +429,29 @@ namespace Sass { ...@@ -415,19 +429,29 @@ namespace Sass {
in_comma_array = was_comma_array; in_comma_array = was_comma_array;
in_space_array = was_space_array; in_space_array = was_space_array;
// if the list is bracketed, always include the right bracket
if (list->is_bracketed()) {
if (list->separator() == SASS_COMMA && list->size() == 1) {
append_string(",");
}
append_string(rbracket(list));
}
// probably ruby sass eqivalent of element_needs_parens // probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS && else if (output_style() == TO_SASS &&
list->length() == 1 && list->length() == 1 &&
!list->from_selector() && !list->from_selector() &&
!SASS_MEMORY_CAST(List, list->at(0)) && !Cast<List>(list->at(0)) &&
!SASS_MEMORY_CAST(Selector_List, list->at(0))) { !Cast<Selector_List>(list->at(0))
append_string(",)"); ) {
append_string(",");
append_string(rbracket(list));
} }
else if (!in_declaration && (list->separator() == SASS_HASH || else if (!in_declaration && (list->separator() == SASS_HASH ||
(list->separator() == SASS_SPACE && in_space_array) || (list->separator() == SASS_SPACE && in_space_array) ||
(list->separator() == SASS_COMMA && in_comma_array) (list->separator() == SASS_COMMA && in_comma_array)
)) { )) {
append_string(")"); append_string(rbracket(list));
} }
} }
...@@ -443,7 +467,7 @@ namespace Sass { ...@@ -443,7 +467,7 @@ namespace Sass {
expr->is_right_interpolant()) expr->is_right_interpolant())
)) append_string(" "); )) append_string(" ");
switch (expr->type()) { switch (expr->optype()) {
case Sass_OP::AND: append_string("&&"); break; case Sass_OP::AND: append_string("&&"); break;
case Sass_OP::OR: append_string("||"); break; case Sass_OP::OR: append_string("||"); break;
case Sass_OP::EQ: append_string("=="); break; case Sass_OP::EQ: append_string("=="); break;
...@@ -471,7 +495,7 @@ namespace Sass { ...@@ -471,7 +495,7 @@ namespace Sass {
void Inspect::operator()(Unary_Expression_Ptr expr) void Inspect::operator()(Unary_Expression_Ptr expr)
{ {
if (expr->type() == Unary_Expression::PLUS) append_string("+"); if (expr->optype() == Unary_Expression::PLUS) append_string("+");
else append_string("-"); else append_string("-");
expr->operand()->perform(this); expr->operand()->perform(this);
} }
...@@ -744,9 +768,9 @@ namespace Sass { ...@@ -744,9 +768,9 @@ namespace Sass {
{ {
append_token("not", sn); append_token("not", sn);
append_mandatory_space(); append_mandatory_space();
if (sn->needs_parens(&sn->condition())) append_string("("); if (sn->needs_parens(sn->condition())) append_string("(");
sn->condition()->perform(this); sn->condition()->perform(this);
if (sn->needs_parens(&sn->condition())) append_string(")"); if (sn->needs_parens(sn->condition())) append_string(")");
} }
void Inspect::operator()(Supports_Declaration_Ptr sd) void Inspect::operator()(Supports_Declaration_Ptr sd)
...@@ -766,7 +790,7 @@ namespace Sass { ...@@ -766,7 +790,7 @@ namespace Sass {
void Inspect::operator()(Media_Query_Ptr mq) void Inspect::operator()(Media_Query_Ptr mq)
{ {
size_t i = 0; size_t i = 0;
if (&mq->media_type()) { if (mq->media_type()) {
if (mq->is_negated()) append_string("not "); if (mq->is_negated()) append_string("not ");
else if (mq->is_restricted()) append_string("only "); else if (mq->is_restricted()) append_string("only ");
mq->media_type()->perform(this); mq->media_type()->perform(this);
...@@ -851,7 +875,7 @@ namespace Sass { ...@@ -851,7 +875,7 @@ namespace Sass {
return; return;
} }
if (a->value()->concrete_type() == Expression::STRING) { if (a->value()->concrete_type() == Expression::STRING) {
String_Constant_Ptr s = SASS_MEMORY_CAST(String_Constant, a->value()); String_Constant_Ptr s = Cast<String_Constant>(a->value());
if (s) s->perform(this); if (s) s->perform(this);
} else { } else {
a->value()->perform(this); a->value()->perform(this);
...@@ -919,7 +943,7 @@ namespace Sass { ...@@ -919,7 +943,7 @@ namespace Sass {
append_token(s->ns_name(), s); append_token(s->ns_name(), s);
if (!s->matcher().empty()) { if (!s->matcher().empty()) {
append_string(s->matcher()); append_string(s->matcher());
if (&s->value() && *s->value()) { if (s->value() && *s->value()) {
s->value()->perform(this); s->value()->perform(this);
} }
} }
...@@ -1040,8 +1064,8 @@ namespace Sass { ...@@ -1040,8 +1064,8 @@ namespace Sass {
bool was_comma_array = in_comma_array; bool was_comma_array = in_comma_array;
// probably ruby sass eqivalent of element_needs_parens // probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS && g->length() == 1 && if (output_style() == TO_SASS && g->length() == 1 &&
(!SASS_MEMORY_CAST(List, (*g)[0]) && (!Cast<List>((*g)[0]) &&
!SASS_MEMORY_CAST(Selector_List, (*g)[0]))) { !Cast<Selector_List>((*g)[0]))) {
append_string("("); append_string("(");
} }
else if (!in_declaration && in_comma_array) { else if (!in_declaration && in_comma_array) {
...@@ -1053,7 +1077,7 @@ namespace Sass { ...@@ -1053,7 +1077,7 @@ namespace Sass {
for (size_t i = 0, L = g->length(); i < L; ++i) { for (size_t i = 0, L = g->length(); i < L; ++i) {
if (!in_wrapped && i == 0) append_indentation(); if (!in_wrapped && i == 0) append_indentation();
if ((*g)[i] == 0) continue; if ((*g)[i] == 0) continue;
schedule_mapping(&g->at(i)->last()); schedule_mapping(g->at(i)->last());
// add_open_mapping((*g)[i]->last()); // add_open_mapping((*g)[i]->last());
(*g)[i]->perform(this); (*g)[i]->perform(this);
// add_close_mapping((*g)[i]->last()); // add_close_mapping((*g)[i]->last());
...@@ -1066,8 +1090,8 @@ namespace Sass { ...@@ -1066,8 +1090,8 @@ namespace Sass {
in_comma_array = was_comma_array; in_comma_array = was_comma_array;
// probably ruby sass eqivalent of element_needs_parens // probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS && g->length() == 1 && if (output_style() == TO_SASS && g->length() == 1 &&
(!SASS_MEMORY_CAST(List, (*g)[0]) && (!Cast<List>((*g)[0]) &&
!SASS_MEMORY_CAST(Selector_List, (*g)[0]))) { !Cast<Selector_List>((*g)[0]))) {
append_string(",)"); append_string(",)");
} }
else if (!in_declaration && in_comma_array) { else if (!in_declaration && in_comma_array) {
......
...@@ -92,6 +92,9 @@ namespace Sass { ...@@ -92,6 +92,9 @@ namespace Sass {
virtual void operator()(Complex_Selector_Ptr); virtual void operator()(Complex_Selector_Ptr);
virtual void operator()(Selector_List_Ptr); virtual void operator()(Selector_List_Ptr);
virtual std::string lbracket(List_Ptr);
virtual std::string rbracket(List_Ptr);
// template <typename U> // template <typename U>
// void fallback(U x) { fallback_impl(reinterpret_cast<AST_Node_Ptr>(x)); } // void fallback(U x) { fallback_impl(reinterpret_cast<AST_Node_Ptr>(x)); }
}; };
......
#include "sass.hpp" #include "sass.hpp"
#include <cctype> #include <cctype>
#include <cstddef>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "lexer.hpp" #include "lexer.hpp"
......
...@@ -70,7 +70,7 @@ namespace Sass { ...@@ -70,7 +70,7 @@ namespace Sass {
if (tail) if (tail)
{ {
Expression_Obj tt = tail->perform(this); Expression_Obj tt = tail->perform(this);
if (List_Ptr ls = SASS_MEMORY_CAST(List, tt)) if (List_Ptr ls = Cast<List>(tt))
{ l->concat(ls); } { l->concat(ls); }
} }
if (l->length() == 0) return 0; if (l->length() == 0) return 0;
...@@ -79,7 +79,7 @@ namespace Sass { ...@@ -79,7 +79,7 @@ namespace Sass {
Expression_Ptr Listize::fallback_impl(AST_Node_Ptr n) Expression_Ptr Listize::fallback_impl(AST_Node_Ptr n)
{ {
return dynamic_cast<Expression_Ptr>(n); return Cast<Expression>(n);
} }
} }
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
namespace Sass { namespace Sass {
typedef Environment<AST_Node_Obj> Env;
struct Backtrace; struct Backtrace;
class Listize : public Operation_CRTP<Expression_Ptr, Listize> { class Listize : public Operation_CRTP<Expression_Ptr, Listize> {
......
...@@ -18,7 +18,7 @@ namespace Sass { ...@@ -18,7 +18,7 @@ namespace Sass {
std::cerr << "# REPORTING MISSING DEALLOCATIONS #\n"; std::cerr << "# REPORTING MISSING DEALLOCATIONS #\n";
std::cerr << "###################################\n"; std::cerr << "###################################\n";
for (auto var : all) { for (auto var : all) {
if (AST_Node_Ptr ast = SASS_MEMORY_CAST_PTR(AST_Node, var)) { if (AST_Node_Ptr ast = Cast<AST_Node>(var)) {
debug_ast(ast); debug_ast(ast);
} else { } else {
std::cerr << "LEAKED " << var << "\n"; std::cerr << "LEAKED " << var << "\n";
...@@ -62,7 +62,7 @@ namespace Sass { ...@@ -62,7 +62,7 @@ namespace Sass {
#endif #endif
if (node->refcounter == 0) { if (node->refcounter == 0) {
#ifdef DEBUG_SHARED_PTR #ifdef DEBUG_SHARED_PTR
AST_Node_Ptr ptr = SASS_MEMORY_CAST_PTR(AST_Node, node); AST_Node_Ptr ptr = Cast<AST_Node>(node);
if (node->dbg) std::cerr << "DELETE NODE " << node << "\n"; if (node->dbg) std::cerr << "DELETE NODE " << node << "\n";
#endif #endif
if (!node->detached) { if (!node->detached) {
......
...@@ -17,7 +17,7 @@ namespace Sass { ...@@ -17,7 +17,7 @@ namespace Sass {
#ifdef DEBUG_SHARED_PTR #ifdef DEBUG_SHARED_PTR
#define SASS_MEMORY_NEW(Class, ...) \ #define SASS_MEMORY_NEW(Class, ...) \
static_cast<Class##_Ptr>((new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \ ((new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
#define SASS_MEMORY_COPY(obj) \ #define SASS_MEMORY_COPY(obj) \
((obj)->copy(__FILE__, __LINE__)) \ ((obj)->copy(__FILE__, __LINE__)) \
...@@ -38,12 +38,6 @@ namespace Sass { ...@@ -38,12 +38,6 @@ namespace Sass {
#endif #endif
#define SASS_MEMORY_CAST(Class, obj) \
(dynamic_cast<Class##_Ptr>(&obj)) \
#define SASS_MEMORY_CAST_PTR(Class, ptr) \
(dynamic_cast<Class##_Ptr>(ptr)) \
class SharedObj { class SharedObj {
protected: protected:
friend class SharedPtr; friend class SharedPtr;
...@@ -114,13 +108,10 @@ namespace Sass { ...@@ -114,13 +108,10 @@ namespace Sass {
// destructor // destructor
~SharedPtr(); ~SharedPtr();
public: public:
SharedObj* obj () {
return node;
};
SharedObj* obj () const { SharedObj* obj () const {
return node; return node;
}; };
SharedObj* operator-> () { SharedObj* operator-> () const {
return node; return node;
}; };
bool isNull () { bool isNull () {
...@@ -129,68 +120,58 @@ namespace Sass { ...@@ -129,68 +120,58 @@ namespace Sass {
bool isNull () const { bool isNull () const {
return node == NULL; return node == NULL;
}; };
SharedObj* detach() {
node->detached = true;
return node;
};
SharedObj* detach() const { SharedObj* detach() const {
if (node) { if (node) {
node->detached = true; node->detached = true;
} }
return node; return node;
}; };
operator bool() {
return node != NULL;
};
operator bool() const { operator bool() const {
return node != NULL; return node != NULL;
}; };
}; };
template < typename T > template < class T >
class SharedImpl : private SharedPtr { class SharedImpl : private SharedPtr {
public: public:
SharedImpl() SharedImpl()
: SharedPtr(NULL) {}; : SharedPtr(NULL) {};
SharedImpl(T* node) SharedImpl(T* node)
: SharedPtr(node) {}; : SharedPtr(node) {};
template < class U >
SharedImpl(SharedImpl<U> obj)
: SharedPtr(static_cast<T*>(obj.ptr())) {}
SharedImpl(T&& node) SharedImpl(T&& node)
: SharedPtr(node) {}; : SharedPtr(node) {};
SharedImpl(const T& node) SharedImpl(const T& node)
: SharedPtr(node) {}; : SharedPtr(node) {};
~SharedImpl() {}; ~SharedImpl() {};
public: public:
T* operator& () { operator T*() const {
return static_cast<T*>(this->obj()); return static_cast<T*>(this->obj());
}; }
T* operator& () const { operator T&() const {
return static_cast<T*>(this->obj());
};
T& operator* () {
return *static_cast<T*>(this->obj()); return *static_cast<T*>(this->obj());
}; }
T& operator* () const { T& operator* () const {
return *static_cast<T*>(this->obj()); return *static_cast<T*>(this->obj());
}; };
T* operator-> () {
return static_cast<T*>(this->obj());
};
T* operator-> () const { T* operator-> () const {
return static_cast<T*>(this->obj()); return static_cast<T*>(this->obj());
}; };
T* ptr () { T* ptr () const {
return static_cast<T*>(this->obj()); return static_cast<T*>(this->obj());
}; };
T* detach() { T* detach() const {
if (this->obj() == NULL) return NULL; if (this->obj() == NULL) return NULL;
return static_cast<T*>(SharedPtr::detach()); return static_cast<T*>(SharedPtr::detach());
} }
bool isNull() { bool isNull() const {
return this->obj() == NULL; return this->obj() == NULL;
} }
operator bool() { bool operator<(const T& rhs) const {
return this->obj() != NULL; return *this->ptr() < rhs;
}; };
operator bool() const { operator bool() const {
return this->obj() != NULL; return this->obj() != NULL;
......
...@@ -71,7 +71,7 @@ namespace Sass { ...@@ -71,7 +71,7 @@ namespace Sass {
for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) { for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
Node& toTest = *iter; Node& toTest = *iter;
if (nodesEqual(toTest, potentialChild, simpleSelectorOrderDependent)) { if (toTest == potentialChild) {
found = true; found = true;
break; break;
} }
...@@ -82,37 +82,32 @@ namespace Sass { ...@@ -82,37 +82,32 @@ namespace Sass {
bool Node::operator==(const Node& rhs) const { bool Node::operator==(const Node& rhs) const {
return nodesEqual(*this, rhs, true /*simpleSelectorOrderDependent*/); if (this->type() != rhs.type()) {
}
bool nodesEqual(const Node& lhs, const Node& rhs, bool simpleSelectorOrderDependent) {
if (lhs.type() != rhs.type()) {
return false; return false;
} }
if (lhs.isCombinator()) { if (this->isCombinator()) {
return lhs.combinator() == rhs.combinator(); return this->combinator() == rhs.combinator();
} else if (lhs.isNil()) { } else if (this->isNil()) {
return true; // no state to check return true; // no state to check
} else if (lhs.isSelector()){ } else if (this->isSelector()){
return selectors_equal(*&lhs.selector(), *&rhs.selector(), simpleSelectorOrderDependent); return *this->selector() == *rhs.selector();
} else if (lhs.isCollection()) { } else if (this->isCollection()) {
if (lhs.collection()->size() != rhs.collection()->size()) { if (this->collection()->size() != rhs.collection()->size()) {
return false; return false;
} }
for (NodeDeque::iterator lhsIter = lhs.collection()->begin(), lhsIterEnd = lhs.collection()->end(), for (NodeDeque::iterator lhsIter = this->collection()->begin(), lhsIterEnd = this->collection()->end(),
rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) { rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) {
if (!nodesEqual(*lhsIter, *rhsIter, simpleSelectorOrderDependent)) { if (*lhsIter != *rhsIter) {
return false; return false;
} }
...@@ -189,7 +184,7 @@ namespace Sass { ...@@ -189,7 +184,7 @@ namespace Sass {
if (pToConvert->head() && pToConvert->head()->has_parent_ref()) { if (pToConvert->head() && pToConvert->head()->has_parent_ref()) {
Complex_Selector_Obj tail = pToConvert->tail(); Complex_Selector_Obj tail = pToConvert->tail();
if (tail) tail->has_line_feed(pToConvert->has_line_feed()); if (tail) tail->has_line_feed(pToConvert->has_line_feed());
pToConvert = &tail; pToConvert = tail;
} }
while (pToConvert) { while (pToConvert) {
...@@ -216,7 +211,7 @@ namespace Sass { ...@@ -216,7 +211,7 @@ namespace Sass {
// pToConvert->tail()->has_line_feed(pToConvert->has_line_feed()); // pToConvert->tail()->has_line_feed(pToConvert->has_line_feed());
} }
pToConvert = &pToConvert->tail(); pToConvert = pToConvert->tail();
} }
return node; return node;
...@@ -254,7 +249,7 @@ namespace Sass { ...@@ -254,7 +249,7 @@ namespace Sass {
// collections, and can result in an infinite loop during the call to parentSuperselector() // collections, and can result in an infinite loop during the call to parentSuperselector()
pCurrent->tail(SASS_MEMORY_COPY(child.selector())); pCurrent->tail(SASS_MEMORY_COPY(child.selector()));
// if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed); // if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed);
pCurrent = &pCurrent->tail(); pCurrent = pCurrent->tail();
} else if (child.isCombinator()) { } else if (child.isCombinator()) {
pCurrent->combinator(child.combinator()); pCurrent->combinator(child.combinator());
if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed); if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed);
...@@ -265,7 +260,7 @@ namespace Sass { ...@@ -265,7 +260,7 @@ namespace Sass {
if (nextNode.isCombinator()) { if (nextNode.isCombinator()) {
pCurrent->tail(SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, NULL, NULL)); pCurrent->tail(SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, NULL, NULL));
if (nextNode.got_line_feed) pCurrent->tail()->has_line_feed(nextNode.got_line_feed); if (nextNode.got_line_feed) pCurrent->tail()->has_line_feed(nextNode.got_line_feed);
pCurrent = &pCurrent->tail(); pCurrent = pCurrent->tail();
} }
} }
} else { } else {
......
...@@ -113,8 +113,6 @@ namespace Sass { ...@@ -113,8 +113,6 @@ namespace Sass {
Node complexSelectorToNode(Complex_Selector_Ptr pToConvert, Context& ctx); Node complexSelectorToNode(Complex_Selector_Ptr pToConvert, Context& ctx);
Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert, Context& ctx); Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert, Context& ctx);
bool nodesEqual(const Node& one, const Node& two, bool simpleSelectorOrderDependent);
} }
#endif #endif
...@@ -116,8 +116,8 @@ namespace Sass { ...@@ -116,8 +116,8 @@ namespace Sass {
if (!Util::isPrintable(r, output_style())) { if (!Util::isPrintable(r, output_style())) {
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
const Statement_Obj& stm = b->at(i); const Statement_Obj& stm = b->at(i);
if (dynamic_cast<Has_Block_Ptr>(&stm)) { if (Cast<Has_Block>(stm)) {
if (!dynamic_cast<Declaration_Ptr>(&stm)) { if (!Cast<Declaration>(stm)) {
stm->perform(this); stm->perform(this);
} }
} }
...@@ -135,27 +135,27 @@ namespace Sass { ...@@ -135,27 +135,27 @@ namespace Sass {
append_optional_linefeed(); append_optional_linefeed();
} }
if (s) s->perform(this); if (s) s->perform(this);
append_scope_opener(&b); append_scope_opener(b);
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
bool bPrintExpression = true; bool bPrintExpression = true;
// Check print conditions // Check print conditions
if (Declaration_Ptr dec = SASS_MEMORY_CAST(Declaration, stm)) { if (Declaration_Ptr dec = Cast<Declaration>(stm)) {
if (String_Constant_Ptr valConst = SASS_MEMORY_CAST(String_Constant, dec->value())) { if (String_Constant_Ptr valConst = Cast<String_Constant>(dec->value())) {
std::string val(valConst->value()); std::string val(valConst->value());
if (String_Quoted_Ptr qstr = SASS_MEMORY_CAST_PTR(String_Quoted, valConst)) { if (String_Quoted_Ptr qstr = Cast<String_Quoted>(valConst)) {
if (!qstr->quote_mark() && val.empty()) { if (!qstr->quote_mark() && val.empty()) {
bPrintExpression = false; bPrintExpression = false;
} }
} }
} }
else if (List_Ptr list = SASS_MEMORY_CAST(List, dec->value())) { else if (List_Ptr list = Cast<List>(dec->value())) {
bool all_invisible = true; bool all_invisible = true;
for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) { for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
Expression_Ptr item = &list->at(list_i); Expression_Ptr item = list->at(list_i);
if (!item->is_invisible()) all_invisible = false; if (!item->is_invisible()) all_invisible = false;
} }
if (all_invisible) bPrintExpression = false; if (all_invisible && !list->is_bracketed()) bPrintExpression = false;
} }
} }
// Print if OK // Print if OK
...@@ -164,7 +164,7 @@ namespace Sass { ...@@ -164,7 +164,7 @@ namespace Sass {
} }
} }
if (output_style() == NESTED) indentation -= r->tabs(); if (output_style() == NESTED) indentation -= r->tabs();
append_scope_closer(&b); append_scope_closer(b);
} }
void Output::operator()(Keyframe_Rule_Ptr r) void Output::operator()(Keyframe_Rule_Ptr r)
...@@ -172,7 +172,7 @@ namespace Sass { ...@@ -172,7 +172,7 @@ namespace Sass {
Block_Obj b = r->block(); Block_Obj b = r->block();
Selector_Obj v = r->name(); Selector_Obj v = r->name();
if (&v) { if (!v.isNull()) {
v->perform(this); v->perform(this);
} }
...@@ -201,7 +201,7 @@ namespace Sass { ...@@ -201,7 +201,7 @@ namespace Sass {
if (!Util::isPrintable(f, output_style())) { if (!Util::isPrintable(f, output_style())) {
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
if (dynamic_cast<Has_Block_Ptr>(&stm)) { if (Cast<Has_Block>(stm)) {
stm->perform(this); stm->perform(this);
} }
} }
...@@ -237,7 +237,7 @@ namespace Sass { ...@@ -237,7 +237,7 @@ namespace Sass {
if (!Util::isPrintable(m, output_style())) { if (!Util::isPrintable(m, output_style())) {
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
if (dynamic_cast<Has_Block_Ptr>(&stm)) { if (Cast<Has_Block>(stm)) {
stm->perform(this); stm->perform(this);
} }
} }
...@@ -282,7 +282,7 @@ namespace Sass { ...@@ -282,7 +282,7 @@ namespace Sass {
if (v) { if (v) {
append_mandatory_space(); append_mandatory_space();
// ruby sass bug? should use options? // ruby sass bug? should use options?
append_token(v->to_string(/* opt */), &v); append_token(v->to_string(/* opt */), v);
} }
if (!b) { if (!b) {
append_delimiter(); append_delimiter();
......
...@@ -39,12 +39,11 @@ namespace Sass { ...@@ -39,12 +39,11 @@ namespace Sass {
Token lexed; Token lexed;
bool in_at_root;
Parser(Context& ctx, const ParserState& pstate) Parser(Context& ctx, const ParserState& pstate)
: ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(), : ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(),
source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0) source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0)
{ in_at_root = false; stack.push_back(Scope::Root); } { stack.push_back(Scope::Root); }
// static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]")); // static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0); static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
...@@ -240,10 +239,10 @@ namespace Sass { ...@@ -240,10 +239,10 @@ namespace Sass {
Arguments_Obj parse_arguments(); Arguments_Obj parse_arguments();
Argument_Obj parse_argument(); Argument_Obj parse_argument();
Assignment_Obj parse_assignment(); Assignment_Obj parse_assignment();
Ruleset_Obj parse_ruleset(Lookahead lookahead, bool is_root = false); Ruleset_Obj parse_ruleset(Lookahead lookahead);
Selector_Schema_Obj parse_selector_schema(const char* end_of_selector); Selector_List_Obj parse_selector_list(bool chroot);
Selector_List_Obj parse_selector_list(bool at_root = false); Complex_Selector_Obj parse_complex_selector(bool chroot);
Complex_Selector_Obj parse_complex_selector(bool in_root = true); Selector_Schema_Obj parse_selector_schema(const char* end_of_selector, bool chroot);
Compound_Selector_Obj parse_compound_selector(); Compound_Selector_Obj parse_compound_selector();
Simple_Selector_Obj parse_simple_selector(); Simple_Selector_Obj parse_simple_selector();
Wrapped_Selector_Obj parse_negated_selector(); Wrapped_Selector_Obj parse_negated_selector();
...@@ -257,6 +256,7 @@ namespace Sass { ...@@ -257,6 +256,7 @@ namespace Sass {
bool parse_number_prefix(); bool parse_number_prefix();
Declaration_Obj parse_declaration(); Declaration_Obj parse_declaration();
Expression_Obj parse_map(); Expression_Obj parse_map();
Expression_Obj parse_bracket_list();
Expression_Obj parse_list(bool delayed = false); Expression_Obj parse_list(bool delayed = false);
Expression_Obj parse_comma_list(bool delayed = false); Expression_Obj parse_comma_list(bool delayed = false);
Expression_Obj parse_space_list(); Expression_Obj parse_space_list();
...@@ -340,15 +340,15 @@ namespace Sass { ...@@ -340,15 +340,15 @@ namespace Sass {
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
if (position[0] == '#' && position[1] == '{') { if (position[0] == '#' && position[1] == '{') {
Expression_Obj itpl = lex_interpolation(); Expression_Obj itpl = lex_interpolation();
if (&itpl) schema->append(&itpl); if (!itpl.isNull()) schema->append(itpl);
while (lex < close >(false)) { while (lex < close >(false)) {
// std::cerr << "LEX [[" << std::string(lexed) << "]]\n"; // std::cerr << "LEX [[" << std::string(lexed) << "]]\n";
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed)); schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
if (position[0] == '#' && position[1] == '{') { if (position[0] == '#' && position[1] == '{') {
Expression_Obj itpl = lex_interpolation(); Expression_Obj itpl = lex_interpolation();
if (&itpl) schema->append(&itpl); if (!itpl.isNull()) schema->append(itpl);
} else { } else {
return &schema; return schema;
} }
} }
} else { } else {
......
#include "sass.hpp"
#include <iostream>
#include "output.hpp"
#include "plugins.hpp"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#else #else
...@@ -7,15 +12,21 @@ ...@@ -7,15 +12,21 @@
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
#include "sass.hpp"
#include <iostream>
#include "output.hpp"
#include "plugins.hpp"
namespace Sass { namespace Sass {
Plugins::Plugins(void) { } Plugins::Plugins(void) { }
Plugins::~Plugins(void) { } Plugins::~Plugins(void)
{
for (auto function : functions) {
sass_delete_function(function);
}
for (auto importer : importers) {
sass_delete_importer(importer);
}
for (auto header : headers) {
sass_delete_importer(header);
}
}
// check if plugin is compatible with this version // check if plugin is compatible with this version
// plugins may be linked static against libsass // plugins may be linked static against libsass
...@@ -57,20 +68,23 @@ namespace Sass { ...@@ -57,20 +68,23 @@ namespace Sass {
// try to get import address for "libsass_load_functions" // try to get import address for "libsass_load_functions"
if (LOAD_LIB_FN(__plugin_load_fns__, plugin_load_functions, "libsass_load_functions")) if (LOAD_LIB_FN(__plugin_load_fns__, plugin_load_functions, "libsass_load_functions"))
{ {
Sass_Function_List fns = plugin_load_functions(); Sass_Function_List fns = plugin_load_functions(), _p = fns;
while (fns && *fns) { functions.push_back(*fns); ++ fns; } while (fns && *fns) { functions.push_back(*fns); ++ fns; }
sass_free_memory(_p); // only delete the container, items not yet
} }
// try to get import address for "libsass_load_importers" // try to get import address for "libsass_load_importers"
if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_importers, "libsass_load_importers")) if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_importers, "libsass_load_importers"))
{ {
Sass_Importer_List imps = plugin_load_importers(); Sass_Importer_List imps = plugin_load_importers(), _p = imps;
while (imps && *imps) { importers.push_back(*imps); ++ imps; } while (imps && *imps) { importers.push_back(*imps); ++ imps; }
sass_free_memory(_p); // only delete the container, items not yet
} }
// try to get import address for "libsass_load_headers" // try to get import address for "libsass_load_headers"
if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_headers, "libsass_load_headers")) if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_headers, "libsass_load_headers"))
{ {
Sass_Importer_List imps = plugin_load_headers(); Sass_Importer_List imps = plugin_load_headers(), _p = imps;
while (imps && *imps) { headers.push_back(*imps); ++ imps; } while (imps && *imps) { headers.push_back(*imps); ++ imps; }
sass_free_memory(_p); // only delete the container, items not yet
} }
// success // success
return true; return true;
...@@ -153,7 +167,11 @@ namespace Sass { ...@@ -153,7 +167,11 @@ namespace Sass {
struct dirent *dirp; struct dirent *dirp;
if((dp = opendir(path.c_str())) == NULL) return -1; if((dp = opendir(path.c_str())) == NULL) return -1;
while ((dirp = readdir(dp)) != NULL) { while ((dirp = readdir(dp)) != NULL) {
#if __APPLE__
if (!ends_with(dirp->d_name, ".dylib")) continue;
#else
if (!ends_with(dirp->d_name, ".so")) continue; if (!ends_with(dirp->d_name, ".so")) continue;
#endif
if (load_plugin(path + dirp->d_name)) ++ loaded; if (load_plugin(path + dirp->d_name)) ++ loaded;
} }
closedir(dp); closedir(dp);
......
...@@ -85,7 +85,7 @@ namespace Sass { ...@@ -85,7 +85,7 @@ namespace Sass {
size_t length() const { return end - begin; } size_t length() const { return end - begin; }
std::string ws_before() const { return std::string(prefix, begin); } std::string ws_before() const { return std::string(prefix, begin); }
std::string to_string() const { return std::string(begin, end); } const std::string to_string() const { return std::string(begin, end); }
std::string time_wspace() const { std::string time_wspace() const {
std::string str(to_string()); std::string str(to_string());
std::string whitespaces(" \t\f\v\n\r"); std::string whitespaces(" \t\f\v\n\r");
......
#include "sass.hpp" #include "sass.hpp"
#include <cctype> #include <cctype>
#include <cstddef>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "util.hpp" #include "util.hpp"
...@@ -1420,6 +1419,28 @@ namespace Sass { ...@@ -1420,6 +1419,28 @@ namespace Sass {
>(src); >(src);
} }
const char* list_terminator(const char* src) {
return alternatives <
exactly<';'>,
exactly<'}'>,
exactly<'{'>,
exactly<')'>,
exactly<']'>,
exactly<':'>,
end_of_file,
exactly<ellipsis>,
default_flag,
global_flag
>(src);
};
const char* space_list_terminator(const char* src) {
return alternatives <
exactly<','>,
list_terminator
>(src);
};
// const char* real_uri_prefix(const char* src) { // const char* real_uri_prefix(const char* src) {
// return alternatives< // return alternatives<
......
...@@ -355,6 +355,10 @@ namespace Sass { ...@@ -355,6 +355,10 @@ namespace Sass {
const char* ie_keyword_arg_value(const char* src); const char* ie_keyword_arg_value(const char* src);
const char* ie_keyword_arg_property(const char* src); const char* ie_keyword_arg_property(const char* src);
// characters that terminate parsing of a list
const char* list_terminator(const char* src);
const char* space_list_terminator(const char* src);
// match url() // match url()
const char* H(const char* src); const char* H(const char* src);
const char* W(const char* src); const char* W(const char* src);
......
...@@ -6,13 +6,12 @@ ...@@ -6,13 +6,12 @@
namespace Sass { namespace Sass {
Remove_Placeholders::Remove_Placeholders(Context& ctx) Remove_Placeholders::Remove_Placeholders()
: ctx(ctx)
{ } { }
void Remove_Placeholders::operator()(Block_Ptr b) { void Remove_Placeholders::operator()(Block_Ptr b) {
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Ptr st = &b->at(i); Statement_Ptr st = b->at(i);
st->perform(this); st->perform(this);
} }
} }
...@@ -34,18 +33,18 @@ namespace Sass { ...@@ -34,18 +33,18 @@ namespace Sass {
void Remove_Placeholders::operator()(Ruleset_Ptr r) { void Remove_Placeholders::operator()(Ruleset_Ptr r) {
// Create a new selector group without placeholders // Create a new selector group without placeholders
Selector_List_Obj sl = SASS_MEMORY_CAST(Selector_List, r->selector()); Selector_List_Obj sl = Cast<Selector_List>(r->selector());
if (sl) { if (sl) {
// Set the new placeholder selector list // Set the new placeholder selector list
r->selector(remove_placeholders(&sl)); r->selector(remove_placeholders(sl));
// Remove placeholders in wrapped selectors // Remove placeholders in wrapped selectors
for (Complex_Selector_Obj cs : sl->elements()) { for (Complex_Selector_Obj cs : sl->elements()) {
while (cs) { while (cs) {
if (cs->head()) { if (cs->head()) {
for (Simple_Selector_Obj& ss : cs->head()->elements()) { for (Simple_Selector_Obj& ss : cs->head()->elements()) {
if (Wrapped_Selector_Ptr ws = SASS_MEMORY_CAST(Wrapped_Selector, ss)) { if (Wrapped_Selector_Ptr ws = Cast<Wrapped_Selector>(ss)) {
if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, ws->selector())) { if (Selector_List_Ptr sl = Cast<Selector_List>(ws->selector())) {
Selector_List_Ptr clean = remove_placeholders(sl); Selector_List_Ptr clean = remove_placeholders(sl);
// also clean superflous parent selectors // also clean superflous parent selectors
// probably not really the correct place // probably not really the correct place
...@@ -72,10 +71,10 @@ namespace Sass { ...@@ -72,10 +71,10 @@ namespace Sass {
} }
void Remove_Placeholders::operator()(Media_Block_Ptr m) { void Remove_Placeholders::operator()(Media_Block_Ptr m) {
operator()(&m->block()); operator()(m->block());
} }
void Remove_Placeholders::operator()(Supports_Block_Ptr m) { void Remove_Placeholders::operator()(Supports_Block_Ptr m) {
operator()(&m->block()); operator()(m->block());
} }
void Remove_Placeholders::operator()(Directive_Ptr a) { void Remove_Placeholders::operator()(Directive_Ptr a) {
......
...@@ -9,19 +9,15 @@ ...@@ -9,19 +9,15 @@
namespace Sass { namespace Sass {
class Context;
class Remove_Placeholders : public Operation_CRTP<void, Remove_Placeholders> { class Remove_Placeholders : public Operation_CRTP<void, Remove_Placeholders> {
Context& ctx;
void fallback_impl(AST_Node_Ptr n) {} void fallback_impl(AST_Node_Ptr n) {}
public: public:
Selector_List_Ptr remove_placeholders(Selector_List_Ptr); Selector_List_Ptr remove_placeholders(Selector_List_Ptr);
public: public:
Remove_Placeholders(Context&); Remove_Placeholders();
~Remove_Placeholders() { } ~Remove_Placeholders() { }
void operator()(Block_Ptr); void operator()(Block_Ptr);
......
...@@ -7,6 +7,23 @@ ...@@ -7,6 +7,23 @@
#include "sass.h" #include "sass.h"
#include "file.hpp" #include "file.hpp"
#include "util.hpp" #include "util.hpp"
#include "sass_context.hpp"
#include "sass_functions.hpp"
namespace Sass {
// helper to convert string list to vector
std::vector<std::string> list2vec(struct string_list* cur)
{
std::vector<std::string> list;
while (cur) {
list.push_back(cur->string);
cur = cur->next;
}
return list;
}
}
extern "C" { extern "C" {
using namespace Sass; using namespace Sass;
...@@ -49,11 +66,50 @@ extern "C" { ...@@ -49,11 +66,50 @@ extern "C" {
return sass_copy_c_string(unquoted.c_str()); return sass_copy_c_string(unquoted.c_str());
} }
char* ADDCALL sass_compiler_find_include (const char* file, struct Sass_Compiler* compiler)
{
// get the last import entry to get current base directory
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
// create the vector with paths to lookup
std::vector<std::string> paths(1 + incs.size());
paths.push_back(File::dir_name(import->abs_path));
paths.insert( paths.end(), incs.begin(), incs.end() );
// now resolve the file path relative to lookup paths
std::string resolved(File::find_include(file, paths));
return sass_copy_c_string(resolved.c_str());
}
char* ADDCALL sass_compiler_find_file (const char* file, struct Sass_Compiler* compiler)
{
// get the last import entry to get current base directory
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
// create the vector with paths to lookup
std::vector<std::string> paths(1 + incs.size());
paths.push_back(File::dir_name(import->abs_path));
paths.insert( paths.end(), incs.begin(), incs.end() );
// now resolve the file path relative to lookup paths
std::string resolved(File::find_file(file, paths));
return sass_copy_c_string(resolved.c_str());
}
// Make sure to free the returned value! // Make sure to free the returned value!
// Incs array has to be null terminated! // Incs array has to be null terminated!
char* ADDCALL sass_resolve_file (const char* file, const char* paths[]) // this has the original resolve logic for sass include
char* ADDCALL sass_find_include (const char* file, struct Sass_Options* opt)
{ {
std::string resolved(File::find_file(file, paths)); std::vector<std::string> vec(list2vec(opt->include_paths));
std::string resolved(File::find_include(file, vec));
return sass_copy_c_string(resolved.c_str());
}
// Make sure to free the returned value!
// Incs array has to be null terminated!
char* ADDCALL sass_find_file (const char* file, struct Sass_Options* opt)
{
std::vector<std::string> vec(list2vec(opt->include_paths));
std::string resolved(File::find_file(file, vec));
return sass_copy_c_string(resolved.c_str()); return sass_copy_c_string(resolved.c_str());
} }
......
...@@ -272,10 +272,14 @@ extern "C" { ...@@ -272,10 +272,14 @@ extern "C" {
#define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \ #define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \
type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \ type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) { options->option = option; } void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) { options->option = option; }
#define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \ #define IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \
type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return safe_str(options->option, def); } \ type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return safe_str(options->option, def); }
#define IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) \
void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \ void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \
{ free(options->option); options->option = option || def ? sass_copy_c_string(option ? option : def) : 0; } { free(options->option); options->option = option || def ? sass_copy_c_string(option ? option : def) : 0; }
#define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \
IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \
IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def)
#define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \ #define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \
type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; } type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; }
...@@ -468,7 +472,7 @@ extern "C" { ...@@ -468,7 +472,7 @@ extern "C" {
if (compiler->c_ctx->error_status) if (compiler->c_ctx->error_status)
return compiler->c_ctx->error_status; return compiler->c_ctx->error_status;
// parse the context we have set up (file or data) // parse the context we have set up (file or data)
compiler->root = &sass_parse_block(compiler); compiler->root = sass_parse_block(compiler);
// success // success
return 0; return 0;
} }
...@@ -674,6 +678,10 @@ extern "C" { ...@@ -674,6 +678,10 @@ extern "C" {
size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.size(); } size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.size(); }
Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.back(); } Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.back(); }
Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx) { return compiler->cpp_ctx->import_stack[idx]; } Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx) { return compiler->cpp_ctx->import_stack[idx]; }
// Getters for Sass_Compiler options (query function stack)
size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->callee_stack.size(); }
Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler) { return &compiler->cpp_ctx->callee_stack.back(); }
Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx) { return &compiler->cpp_ctx->callee_stack[idx]; }
// Calculate the size of the stored null terminated array // Calculate the size of the stored null terminated array
size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx) size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx)
...@@ -693,10 +701,10 @@ extern "C" { ...@@ -693,10 +701,10 @@ extern "C" {
IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_headers); IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_headers);
IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent); IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent);
IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed); IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed);
IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, plugin_path, 0);
IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, include_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path, 0); IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path, 0); IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, plugin_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, include_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file, 0); IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root, 0); IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root, 0);
...@@ -740,6 +748,23 @@ extern "C" { ...@@ -740,6 +748,23 @@ extern "C" {
} }
// Push function for include paths (no manipulation support for now)
size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options)
{
size_t len = 0;
struct string_list* cur = options->include_paths;
while (cur) { len ++; cur = cur->next; }
return len;
}
// Push function for include paths (no manipulation support for now)
const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i)
{
struct string_list* cur = options->include_paths;
while (i) { i--; cur = cur->next; }
return cur->string;
}
// Push function for plugin paths (no manipulation support for now) // Push function for plugin paths (no manipulation support for now)
void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path) void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path)
{ {
......
#ifndef SASS_SASS_CONTEXT_H #ifndef SASS_SASS_CONTEXT_H
#define SASS_SASS_CONTEXT_H #define SASS_SASS_CONTEXT_H
#include "sass.h" #include "sass/base.h"
#include "sass.hpp" #include "sass/context.h"
#include "context.hpp"
#include "ast_fwd_decl.hpp" #include "ast_fwd_decl.hpp"
// sass config options structure // sass config options structure
...@@ -33,7 +32,7 @@ struct Sass_Options : Sass_Output_Options { ...@@ -33,7 +32,7 @@ struct Sass_Options : Sass_Output_Options {
char* input_path; char* input_path;
// The output path is used for source map // The output path is used for source map
// generation. Libsass will not write to // generation. LibSass will not write to
// this file, it is just used to create // this file, it is just used to create
// information in source-maps etc. // information in source-maps etc.
char* output_path; char* output_path;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <cstring> #include <cstring>
#include "util.hpp" #include "util.hpp"
#include "context.hpp" #include "context.hpp"
#include "values.hpp"
#include "sass/functions.h" #include "sass/functions.h"
#include "sass_functions.hpp" #include "sass_functions.hpp"
...@@ -17,12 +18,30 @@ extern "C" { ...@@ -17,12 +18,30 @@ extern "C" {
{ {
Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function)); Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function));
if (cb == 0) return 0; if (cb == 0) return 0;
cb->signature = signature; cb->signature = strdup(signature);
cb->function = function; cb->function = function;
cb->cookie = cookie; cb->cookie = cookie;
return cb; return cb;
} }
void ADDCALL sass_delete_function(Sass_Function_Entry entry)
{
free(entry->signature);
free(entry);
}
// Deallocator for the allocated memory
void ADDCALL sass_delete_function_list(Sass_Function_List list)
{
Sass_Function_List it = list;
if (list == 0) return;
while(*list) {
sass_delete_function(*list);
++list;
}
free(it);
}
// Setters and getters for callbacks on function lists // Setters and getters for callbacks on function lists
Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; } Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; }
void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; } void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; }
...@@ -57,6 +76,18 @@ extern "C" { ...@@ -57,6 +76,18 @@ extern "C" {
return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry)); return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry));
} }
// Deallocator for the allocated memory
void ADDCALL sass_delete_importer_list(Sass_Importer_List list)
{
Sass_Importer_List it = list;
if (list == 0) return;
while(*list) {
sass_delete_importer(*list);
++list;
}
free(it);
}
Sass_Importer_Entry ADDCALL sass_importer_get_list_entry(Sass_Importer_List list, size_t idx) { return list[idx]; } Sass_Importer_Entry ADDCALL sass_importer_get_list_entry(Sass_Importer_List list, size_t idx) { return list[idx]; }
void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) { list[idx] = cb; } void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) { list[idx] = cb; }
...@@ -126,6 +157,37 @@ extern "C" { ...@@ -126,6 +157,37 @@ extern "C" {
free(import); free(import);
} }
// Getter for callee entry
const char* ADDCALL sass_callee_get_name(Sass_Callee_Entry entry) { return entry->name; }
const char* ADDCALL sass_callee_get_path(Sass_Callee_Entry entry) { return entry->path; }
size_t ADDCALL sass_callee_get_line(Sass_Callee_Entry entry) { return entry->line; }
size_t ADDCALL sass_callee_get_column(Sass_Callee_Entry entry) { return entry->column; }
enum Sass_Callee_Type ADDCALL sass_callee_get_type(Sass_Callee_Entry entry) { return entry->type; }
Sass_Env_Frame ADDCALL sass_callee_get_env (Sass_Callee_Entry entry) { return &entry->env; }
// Getters and Setters for environments (lexical, local and global)
union Sass_Value* ADDCALL sass_env_get_lexical (Sass_Env_Frame env, const char* name) {
Expression_Ptr ex = Cast<Expression>((*env->frame)[name]);
return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
}
void ADDCALL sass_env_set_lexical (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
(*env->frame)[name] = sass_value_to_ast_node(val);
}
union Sass_Value* ADDCALL sass_env_get_local (Sass_Env_Frame env, const char* name) {
Expression_Ptr ex = Cast<Expression>(env->frame->get_local(name));
return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
}
void ADDCALL sass_env_set_local (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
env->frame->set_local(name, sass_value_to_ast_node(val));
}
union Sass_Value* ADDCALL sass_env_get_global (Sass_Env_Frame env, const char* name) {
Expression_Ptr ex = Cast<Expression>(env->frame->get_global(name));
return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
}
void ADDCALL sass_env_set_global (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
env->frame->set_global(name, sass_value_to_ast_node(val));
}
// Getter for import entry // Getter for import entry
const char* ADDCALL sass_import_get_imp_path(Sass_Import_Entry entry) { return entry->imp_path; } const char* ADDCALL sass_import_get_imp_path(Sass_Import_Entry entry) { return entry->imp_path; }
const char* ADDCALL sass_import_get_abs_path(Sass_Import_Entry entry) { return entry->abs_path; } const char* ADDCALL sass_import_get_abs_path(Sass_Import_Entry entry) { return entry->abs_path; }
......
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
#define SASS_SASS_FUNCTIONS_H #define SASS_SASS_FUNCTIONS_H
#include "sass.h" #include "sass.h"
#include "environment.hpp"
#include "functions.hpp"
// Struct to hold custom function callback // Struct to hold custom function callback
struct Sass_Function { struct Sass_Function {
const char* signature; char* signature;
Sass_Function_Fn function; Sass_Function_Fn function;
void* cookie; void* cookie;
}; };
...@@ -22,6 +24,22 @@ struct Sass_Import { ...@@ -22,6 +24,22 @@ struct Sass_Import {
size_t column; size_t column;
}; };
// External environments
struct Sass_Env {
// links to parent frames
Sass::Env* frame;
};
// External call entry
struct Sass_Callee {
const char* name;
const char* path;
size_t line;
size_t column;
enum Sass_Callee_Type type;
struct Sass_Env env;
};
// Struct to hold importer callback // Struct to hold importer callback
struct Sass_Importer { struct Sass_Importer {
Sass_Importer_Fn importer; Sass_Importer_Fn importer;
......
...@@ -40,7 +40,7 @@ namespace Sass { ...@@ -40,7 +40,7 @@ namespace Sass {
bool operator()(const Node& one, const Node& two, Node& out) const { bool operator()(const Node& one, const Node& two, Node& out) const {
// TODO: Is this the correct C++ interpretation? // TODO: Is this the correct C++ interpretation?
// block ||= proc {|a, b| a == b && a} // block ||= proc {|a, b| a == b && a}
if (nodesEqual(one, two, true)) { if (one == two) {
out = one; out = one;
return true; return true;
} }
......
...@@ -54,6 +54,8 @@ extern "C" { ...@@ -54,6 +54,8 @@ extern "C" {
size_t ADDCALL sass_list_get_length(const union Sass_Value* v) { return v->list.length; } size_t ADDCALL sass_list_get_length(const union Sass_Value* v) { return v->list.length; }
enum Sass_Separator ADDCALL sass_list_get_separator(const union Sass_Value* v) { return v->list.separator; } enum Sass_Separator ADDCALL sass_list_get_separator(const union Sass_Value* v) { return v->list.separator; }
void ADDCALL sass_list_set_separator(union Sass_Value* v, enum Sass_Separator separator) { v->list.separator = separator; } void ADDCALL sass_list_set_separator(union Sass_Value* v, enum Sass_Separator separator) { v->list.separator = separator; }
bool ADDCALL sass_list_get_is_bracketed(const union Sass_Value* v) { return v->list.is_bracketed; }
void ADDCALL sass_list_set_is_bracketed(union Sass_Value* v, bool is_bracketed) { v->list.is_bracketed = is_bracketed; }
// Getters and setters for Sass_List values // Getters and setters for Sass_List values
union Sass_Value* ADDCALL sass_list_get_value(const union Sass_Value* v, size_t i) { return v->list.values[i]; } union Sass_Value* ADDCALL sass_list_get_value(const union Sass_Value* v, size_t i) { return v->list.values[i]; }
void ADDCALL sass_list_set_value(union Sass_Value* v, size_t i, union Sass_Value* value) { v->list.values[i] = value; } void ADDCALL sass_list_set_value(union Sass_Value* v, size_t i, union Sass_Value* value) { v->list.values[i] = value; }
...@@ -130,13 +132,14 @@ extern "C" { ...@@ -130,13 +132,14 @@ extern "C" {
return v; return v;
} }
union Sass_Value* ADDCALL sass_make_list(size_t len, enum Sass_Separator sep) union Sass_Value* ADDCALL sass_make_list(size_t len, enum Sass_Separator sep, bool is_bracketed)
{ {
union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value)); union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value));
if (v == 0) return 0; if (v == 0) return 0;
v->list.tag = SASS_LIST; v->list.tag = SASS_LIST;
v->list.length = len; v->list.length = len;
v->list.separator = sep; v->list.separator = sep;
v->list.is_bracketed = is_bracketed;
v->list.values = (union Sass_Value**) calloc(len, sizeof(union Sass_Value*)); v->list.values = (union Sass_Value**) calloc(len, sizeof(union Sass_Value*));
if (v->list.values == 0) { free(v); return 0; } if (v->list.values == 0) { free(v); return 0; }
return v; return v;
...@@ -247,7 +250,7 @@ extern "C" { ...@@ -247,7 +250,7 @@ extern "C" {
return sass_string_is_quoted(val) ? sass_make_qstring(val->string.value) : sass_make_string(val->string.value); return sass_string_is_quoted(val) ? sass_make_qstring(val->string.value) : sass_make_string(val->string.value);
} break; } break;
case SASS_LIST: { case SASS_LIST: {
union Sass_Value* list = sass_make_list(val->list.length, val->list.separator); union Sass_Value* list = sass_make_list(val->list.length, val->list.separator, val->list.is_bracketed);
for (i = 0; i < list->list.length; i++) { for (i = 0; i < list->list.length; i++) {
list->list.values[i] = sass_clone_value(val->list.values[i]); list->list.values[i] = sass_clone_value(val->list.values[i]);
} }
...@@ -294,40 +297,40 @@ extern "C" { ...@@ -294,40 +297,40 @@ extern "C" {
// see if it's a relational expression // see if it's a relational expression
switch(op) { switch(op) {
case Sass_OP::EQ: return sass_make_boolean(Eval::eq(&lhs, &rhs)); case Sass_OP::EQ: return sass_make_boolean(Eval::eq(lhs, rhs));
case Sass_OP::NEQ: return sass_make_boolean(!Eval::eq(&lhs, &rhs)); case Sass_OP::NEQ: return sass_make_boolean(!Eval::eq(lhs, rhs));
case Sass_OP::GT: return sass_make_boolean(!Eval::lt(&lhs, &rhs, "gt") && !Eval::eq(&lhs, &rhs)); case Sass_OP::GT: return sass_make_boolean(!Eval::lt(lhs, rhs, "gt") && !Eval::eq(lhs, rhs));
case Sass_OP::GTE: return sass_make_boolean(!Eval::lt(&lhs, &rhs, "gte")); case Sass_OP::GTE: return sass_make_boolean(!Eval::lt(lhs, rhs, "gte"));
case Sass_OP::LT: return sass_make_boolean(Eval::lt(&lhs, &rhs, "lt")); case Sass_OP::LT: return sass_make_boolean(Eval::lt(lhs, rhs, "lt"));
case Sass_OP::LTE: return sass_make_boolean(Eval::lt(&lhs, &rhs, "lte") || Eval::eq(&lhs, &rhs)); case Sass_OP::LTE: return sass_make_boolean(Eval::lt(lhs, rhs, "lte") || Eval::eq(lhs, rhs));
case Sass_OP::AND: return ast_node_to_sass_value(lhs->is_false() ? &lhs : &rhs); case Sass_OP::AND: return ast_node_to_sass_value(lhs->is_false() ? lhs : rhs);
case Sass_OP::OR: return ast_node_to_sass_value(lhs->is_false() ? &rhs : &lhs); case Sass_OP::OR: return ast_node_to_sass_value(lhs->is_false() ? rhs : lhs);
default: break; default: break;
} }
if (sass_value_is_number(a) && sass_value_is_number(b)) { if (sass_value_is_number(a) && sass_value_is_number(b)) {
Number_Ptr_Const l_n = SASS_MEMORY_CAST(Number, lhs); Number_Ptr_Const l_n = Cast<Number>(lhs);
Number_Ptr_Const r_n = SASS_MEMORY_CAST(Number, rhs); Number_Ptr_Const r_n = Cast<Number>(rhs);
rv = Eval::op_numbers(op, *l_n, *r_n, options); rv = Eval::op_numbers(op, *l_n, *r_n, options);
} }
else if (sass_value_is_number(a) && sass_value_is_color(a)) { else if (sass_value_is_number(a) && sass_value_is_color(a)) {
Number_Ptr_Const l_n = SASS_MEMORY_CAST(Number, lhs); Number_Ptr_Const l_n = Cast<Number>(lhs);
Color_Ptr_Const r_c = SASS_MEMORY_CAST(Color, rhs); Color_Ptr_Const r_c = Cast<Color>(rhs);
rv = Eval::op_number_color(op, *l_n, *r_c, options); rv = Eval::op_number_color(op, *l_n, *r_c, options);
} }
else if (sass_value_is_color(a) && sass_value_is_number(b)) { else if (sass_value_is_color(a) && sass_value_is_number(b)) {
Color_Ptr_Const l_c = SASS_MEMORY_CAST(Color, lhs); Color_Ptr_Const l_c = Cast<Color>(lhs);
Number_Ptr_Const r_n = SASS_MEMORY_CAST(Number, rhs); Number_Ptr_Const r_n = Cast<Number>(rhs);
rv = Eval::op_color_number(op, *l_c, *r_n, options); rv = Eval::op_color_number(op, *l_c, *r_n, options);
} }
else if (sass_value_is_color(a) && sass_value_is_color(b)) { else if (sass_value_is_color(a) && sass_value_is_color(b)) {
Color_Ptr_Const l_c = SASS_MEMORY_CAST(Color, lhs); Color_Ptr_Const l_c = Cast<Color>(lhs);
Color_Ptr_Const r_c = SASS_MEMORY_CAST(Color, rhs); Color_Ptr_Const r_c = Cast<Color>(rhs);
rv = Eval::op_colors(op, *l_c, *r_c, options); rv = Eval::op_colors(op, *l_c, *r_c, options);
} }
else /* convert other stuff to string and apply operation */ { else /* convert other stuff to string and apply operation */ {
Value_Ptr l_v = SASS_MEMORY_CAST(Value, lhs); Value_Ptr l_v = Cast<Value>(lhs);
Value_Ptr r_v = SASS_MEMORY_CAST(Value, rhs); Value_Ptr r_v = Cast<Value>(rhs);
rv = Eval::op_strings(op, *l_v, *r_v, options); rv = Eval::op_strings(op, *l_v, *r_v, options);
} }
......
...@@ -35,6 +35,7 @@ struct Sass_String { ...@@ -35,6 +35,7 @@ struct Sass_String {
struct Sass_List { struct Sass_List {
enum Sass_Tag tag; enum Sass_Tag tag;
enum Sass_Separator separator; enum Sass_Separator separator;
bool is_bracketed;
size_t length; size_t length;
// null terminated "array" // null terminated "array"
union Sass_Value** values; union Sass_Value** values;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <cstddef>
#include <iomanip> #include <iomanip>
#include "ast.hpp" #include "ast.hpp"
......
...@@ -4,22 +4,20 @@ ...@@ -4,22 +4,20 @@
namespace Sass { namespace Sass {
void Subset_Map::put(const Compound_Selector_Obj& sel, const Subset_Map_Val& value) void Subset_Map::put(const Compound_Selector_Obj& sel, const SubSetMapPair& value)
{ {
if (sel->empty()) throw std::runtime_error("internal error: subset map keys may not be empty"); if (sel->empty()) throw std::runtime_error("internal error: subset map keys may not be empty");
size_t index = values_.size(); size_t index = values_.size();
values_.push_back(value); values_.push_back(value);
for (size_t i = 0, S = sel->length(); i < S; ++i) for (size_t i = 0, S = sel->length(); i < S; ++i)
{ {
hash_[(*sel)[i]].push_back(std::make_pair(&sel, index)); hash_[(*sel)[i]].push_back(std::make_pair(sel, index));
} }
} }
std::vector<Subset_Map_Val> Subset_Map::get_kv(const Compound_Selector_Obj& sel) std::vector<SubSetMapPair> Subset_Map::get_kv(const Compound_Selector_Obj& sel)
{ {
// std::vector<Subset_Map_Key> s = sel->to_str_vec(); SimpleSelectorDict dict(sel->begin(), sel->end()); // XXX Set
// std::set<std::string> dict(s.begin(), s.end());
std::unordered_set<Simple_Selector_Obj, HashSimpleSelector, CompareSimpleSelector> dict(sel->begin(), sel->end());
std::vector<size_t> indices; std::vector<size_t> indices;
for (size_t i = 0, S = sel->length(); i < S; ++i) { for (size_t i = 0, S = sel->length(); i < S; ++i) {
if (!hash_.count((*sel)[i])) { if (!hash_.count((*sel)[i])) {
...@@ -42,14 +40,14 @@ namespace Sass { ...@@ -42,14 +40,14 @@ namespace Sass {
std::vector<size_t>::iterator indices_end = unique(indices.begin(), indices.end()); std::vector<size_t>::iterator indices_end = unique(indices.begin(), indices.end());
indices.resize(distance(indices.begin(), indices_end)); indices.resize(distance(indices.begin(), indices_end));
std::vector<Subset_Map_Val> results; std::vector<SubSetMapPair> results;
for (size_t i = 0, S = indices.size(); i < S; ++i) { for (size_t i = 0, S = indices.size(); i < S; ++i) {
results.push_back(values_[indices[i]]); results.push_back(values_[indices[i]]);
} }
return results; return results;
} }
std::vector<Subset_Map_Val> Subset_Map::get_v(const Compound_Selector_Obj& sel) std::vector<SubSetMapPair> Subset_Map::get_v(const Compound_Selector_Obj& sel)
{ {
return get_kv(sel); return get_kv(sel);
} }
......
...@@ -60,15 +60,15 @@ namespace Sass { ...@@ -60,15 +60,15 @@ namespace Sass {
class Subset_Map { class Subset_Map {
private: private:
std::vector<Subset_Map_Val> values_; std::vector<SubSetMapPair> values_;
std::map<Simple_Selector_Obj, std::vector<std::pair<Compound_Selector_Obj, size_t> > > hash_; std::map<Simple_Selector_Obj, std::vector<std::pair<Compound_Selector_Obj, size_t> >, OrderNodes > hash_;
public: public:
void put(const Compound_Selector_Obj& sel, const Subset_Map_Val& value); void put(const Compound_Selector_Obj& sel, const SubSetMapPair& value);
std::vector<Subset_Map_Val> get_kv(const Compound_Selector_Obj& s); std::vector<SubSetMapPair> get_kv(const Compound_Selector_Obj& s);
std::vector<Subset_Map_Val> get_v(const Compound_Selector_Obj& s); std::vector<SubSetMapPair> get_v(const Compound_Selector_Obj& s);
bool empty() { return values_.empty(); } bool empty() { return values_.empty(); }
void clear() { values_.clear(); hash_.clear(); } void clear() { values_.clear(); hash_.clear(); }
const std::vector<Subset_Map_Val> values(void) { return values_; } const std::vector<SubSetMapPair> values(void) { return values_; }
}; };
} }
......
...@@ -36,7 +36,7 @@ namespace Sass { ...@@ -36,7 +36,7 @@ namespace Sass {
union Sass_Value* To_C::operator()(List_Ptr l) union Sass_Value* To_C::operator()(List_Ptr l)
{ {
union Sass_Value* v = sass_make_list(l->length(), l->separator()); union Sass_Value* v = sass_make_list(l->length(), l->separator(), l->is_bracketed());
for (size_t i = 0, L = l->length(); i < L; ++i) { for (size_t i = 0, L = l->length(); i < L; ++i) {
sass_list_set_value(v, i, (*l)[i]->perform(this)); sass_list_set_value(v, i, (*l)[i]->perform(this));
} }
...@@ -57,7 +57,7 @@ namespace Sass { ...@@ -57,7 +57,7 @@ namespace Sass {
union Sass_Value* To_C::operator()(Arguments_Ptr a) union Sass_Value* To_C::operator()(Arguments_Ptr a)
{ {
union Sass_Value* v = sass_make_list(a->length(), SASS_COMMA); union Sass_Value* v = sass_make_list(a->length(), SASS_COMMA, false);
for (size_t i = 0, L = a->length(); i < L; ++i) { for (size_t i = 0, L = a->length(); i < L; ++i) {
sass_list_set_value(v, i, (*a)[i]->perform(this)); sass_list_set_value(v, i, (*a)[i]->perform(this));
} }
......
...@@ -445,7 +445,7 @@ namespace Sass { ...@@ -445,7 +445,7 @@ namespace Sass {
Block_Obj b = r->block(); Block_Obj b = r->block();
Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, r->selector()); Selector_List_Ptr sl = Cast<Selector_List>(r->selector());
bool hasSelectors = sl ? sl->length() > 0 : false; bool hasSelectors = sl ? sl->length() > 0 : false;
if (!hasSelectors) { if (!hasSelectors) {
...@@ -456,16 +456,16 @@ namespace Sass { ...@@ -456,16 +456,16 @@ namespace Sass {
bool hasPrintableChildBlocks = false; bool hasPrintableChildBlocks = false;
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
if (dynamic_cast<Directive_Ptr>(&stm)) { if (Cast<Directive>(stm)) {
return true; return true;
} else if (Declaration_Ptr d = dynamic_cast<Declaration_Ptr>(&stm)) { } else if (Declaration_Ptr d = Cast<Declaration>(stm)) {
return isPrintable(d, style); return isPrintable(d, style);
} else if (dynamic_cast<Has_Block_Ptr>(&stm)) { } else if (Has_Block_Ptr p = Cast<Has_Block>(stm)) {
Block_Obj pChildBlock = ((Has_Block_Ptr)&stm)->block(); Block_Obj pChildBlock = p->block();
if (isPrintable(&pChildBlock, style)) { if (isPrintable(pChildBlock, style)) {
hasPrintableChildBlocks = true; hasPrintableChildBlocks = true;
} }
} else if (Comment_Ptr c = dynamic_cast<Comment_Ptr>(&stm)) { } else if (Comment_Ptr c = Cast<Comment>(stm)) {
// keep for uncompressed // keep for uncompressed
if (style != COMPRESSED) { if (style != COMPRESSED) {
hasDeclarations = true; hasDeclarations = true;
...@@ -499,8 +499,8 @@ namespace Sass { ...@@ -499,8 +499,8 @@ namespace Sass {
bool isPrintable(Declaration_Ptr d, Sass_Output_Style style) bool isPrintable(Declaration_Ptr d, Sass_Output_Style style)
{ {
Expression_Obj val = d->value(); Expression_Obj val = d->value();
if (String_Quoted_Obj sq = SASS_MEMORY_CAST(String_Quoted, val)) return isPrintable(&sq, style); if (String_Quoted_Obj sq = Cast<String_Quoted>(val)) return isPrintable(sq.ptr(), style);
if (String_Constant_Obj sc = SASS_MEMORY_CAST(String_Constant, val)) return isPrintable(&sc, style); if (String_Constant_Obj sc = Cast<String_Constant>(val)) return isPrintable(sc.ptr(), style);
return true; return true;
} }
...@@ -511,18 +511,16 @@ namespace Sass { ...@@ -511,18 +511,16 @@ namespace Sass {
Block_Obj b = f->block(); Block_Obj b = f->block();
// bool hasSelectors = f->selector() && static_cast<Selector_List_Ptr>(f->selector())->length() > 0;
bool hasDeclarations = false; bool hasDeclarations = false;
bool hasPrintableChildBlocks = false; bool hasPrintableChildBlocks = false;
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
if (dynamic_cast<Declaration_Ptr>(&stm) || dynamic_cast<Directive_Ptr>(&stm)) { if (Cast<Declaration>(stm) || Cast<Directive>(stm)) {
hasDeclarations = true; hasDeclarations = true;
} }
else if (dynamic_cast<Has_Block_Ptr>(&stm)) { else if (Has_Block_Ptr b = Cast<Has_Block>(stm)) {
Block_Obj pChildBlock = ((Has_Block_Ptr)&stm)->block(); Block_Obj pChildBlock = b->block();
if (isPrintable(&pChildBlock, style)) { if (isPrintable(pChildBlock, style)) {
hasPrintableChildBlocks = true; hasPrintableChildBlocks = true;
} }
} }
...@@ -542,36 +540,34 @@ namespace Sass { ...@@ -542,36 +540,34 @@ namespace Sass {
if (b == 0) return false; if (b == 0) return false;
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
if (dynamic_cast<Directive_Ptr>(&stm)) return true; if (Cast<Directive>(stm)) return true;
else if (dynamic_cast<Declaration_Ptr>(&stm)) return true; else if (Cast<Declaration>(stm)) return true;
else if (dynamic_cast<Comment_Ptr>(&stm)) { else if (Comment_Ptr c = Cast<Comment>(stm)) {
Comment_Ptr c = (Comment_Ptr) &stm;
if (isPrintable(c, style)) { if (isPrintable(c, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Ruleset_Ptr>(&stm)) { else if (Ruleset_Ptr r = Cast<Ruleset>(stm)) {
Ruleset_Ptr r = (Ruleset_Ptr) &stm;
if (isPrintable(r, style)) { if (isPrintable(r, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Supports_Block_Ptr>(&stm)) { else if (Supports_Block_Ptr f = Cast<Supports_Block>(stm)) {
Supports_Block_Ptr f = (Supports_Block_Ptr) &stm;
if (isPrintable(f, style)) { if (isPrintable(f, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Media_Block_Ptr>(&stm)) { else if (Media_Block_Ptr m = Cast<Media_Block>(stm)) {
Media_Block_Ptr m = (Media_Block_Ptr) &stm;
if (isPrintable(m, style)) { if (isPrintable(m, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Has_Block_Ptr>(&stm) && isPrintable(((Has_Block_Ptr)&stm)->block(), style)) { else if (Has_Block_Ptr b = Cast<Has_Block>(stm)) {
if (isPrintable(b->block(), style)) {
return true; return true;
} }
} }
}
return false; return false;
} }
...@@ -596,37 +592,35 @@ namespace Sass { ...@@ -596,37 +592,35 @@ namespace Sass {
for (size_t i = 0, L = b->length(); i < L; ++i) { for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i); Statement_Obj stm = b->at(i);
if (dynamic_cast<Declaration_Ptr>(&stm) || dynamic_cast<Directive_Ptr>(&stm)) { if (Cast<Declaration>(stm) || Cast<Directive>(stm)) {
return true; return true;
} }
else if (dynamic_cast<Comment_Ptr>(&stm)) { else if (Comment_Ptr c = Cast<Comment>(stm)) {
Comment_Ptr c = (Comment_Ptr) &stm;
if (isPrintable(c, style)) { if (isPrintable(c, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Ruleset_Ptr>(&stm)) { else if (Ruleset_Ptr r = Cast<Ruleset>(stm)) {
Ruleset_Ptr r = (Ruleset_Ptr) &stm;
if (isPrintable(r, style)) { if (isPrintable(r, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Supports_Block_Ptr>(&stm)) { else if (Supports_Block_Ptr f = Cast<Supports_Block>(stm)) {
Supports_Block_Ptr f = (Supports_Block_Ptr) &stm;
if (isPrintable(f, style)) { if (isPrintable(f, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Media_Block_Ptr>(&stm)) { else if (Media_Block_Ptr m = Cast<Media_Block>(stm)) {
Media_Block_Ptr m = (Media_Block_Ptr) &stm;
if (isPrintable(m, style)) { if (isPrintable(m, style)) {
return true; return true;
} }
} }
else if (dynamic_cast<Has_Block_Ptr>(&stm) && isPrintable(((Has_Block_Ptr)&stm)->block(), style)) { else if (Has_Block_Ptr b = Cast<Has_Block>(stm)) {
if (isPrintable(b->block(), style)) {
return true; return true;
} }
} }
}
return false; return false;
} }
......
...@@ -11,32 +11,32 @@ namespace Sass { ...@@ -11,32 +11,32 @@ namespace Sass {
{ {
if (val->concrete_type() == Expression::NUMBER) if (val->concrete_type() == Expression::NUMBER)
{ {
Number_Ptr_Const res = dynamic_cast<Number_Ptr_Const>(val); Number_Ptr_Const res = Cast<Number>(val);
return sass_make_number(res->value(), res->unit().c_str()); return sass_make_number(res->value(), res->unit().c_str());
} }
else if (val->concrete_type() == Expression::COLOR) else if (val->concrete_type() == Expression::COLOR)
{ {
Color_Ptr_Const col = dynamic_cast<Color_Ptr_Const>(val); Color_Ptr_Const col = Cast<Color>(val);
return sass_make_color(col->r(), col->g(), col->b(), col->a()); return sass_make_color(col->r(), col->g(), col->b(), col->a());
} }
else if (val->concrete_type() == Expression::LIST) else if (val->concrete_type() == Expression::LIST)
{ {
List_Ptr_Const l = dynamic_cast<List_Ptr_Const>(val); List_Ptr_Const l = Cast<List>(val);
union Sass_Value* list = sass_make_list(l->size(), l->separator()); union Sass_Value* list = sass_make_list(l->size(), l->separator(), l->is_bracketed());
for (size_t i = 0, L = l->length(); i < L; ++i) { for (size_t i = 0, L = l->length(); i < L; ++i) {
Expression_Obj obj = l->at(i); Expression_Obj obj = l->at(i);
auto val = ast_node_to_sass_value(&obj); auto val = ast_node_to_sass_value(obj);
sass_list_set_value(list, i, val); sass_list_set_value(list, i, val);
} }
return list; return list;
} }
else if (val->concrete_type() == Expression::MAP) else if (val->concrete_type() == Expression::MAP)
{ {
Map_Ptr_Const m = dynamic_cast<Map_Ptr_Const>(val); Map_Ptr_Const m = Cast<Map>(val);
union Sass_Value* map = sass_make_map(m->length()); union Sass_Value* map = sass_make_map(m->length());
size_t i = 0; for (Expression_Obj key : m->keys()) { size_t i = 0; for (Expression_Obj key : m->keys()) {
sass_map_set_key(map, i, ast_node_to_sass_value(&key)); sass_map_set_key(map, i, ast_node_to_sass_value(key));
sass_map_set_value(map, i, ast_node_to_sass_value(&m->at(key))); sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key)));
++ i; ++ i;
} }
return map; return map;
...@@ -47,16 +47,16 @@ namespace Sass { ...@@ -47,16 +47,16 @@ namespace Sass {
} }
else if (val->concrete_type() == Expression::BOOLEAN) else if (val->concrete_type() == Expression::BOOLEAN)
{ {
Boolean_Ptr_Const res = dynamic_cast<Boolean_Ptr_Const>(val); Boolean_Ptr_Const res = Cast<Boolean>(val);
return sass_make_boolean(res->value()); return sass_make_boolean(res->value());
} }
else if (val->concrete_type() == Expression::STRING) else if (val->concrete_type() == Expression::STRING)
{ {
if (String_Quoted_Ptr_Const qstr = dynamic_cast<String_Quoted_Ptr_Const>(val)) if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(val))
{ {
return sass_make_qstring(qstr->value().c_str()); return sass_make_qstring(qstr->value().c_str());
} }
else if (String_Constant_Ptr_Const cstr = dynamic_cast<String_Constant_Ptr_Const>(val)) else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(val))
{ {
return sass_make_string(cstr->value().c_str()); return sass_make_string(cstr->value().c_str());
} }
...@@ -106,6 +106,7 @@ namespace Sass { ...@@ -106,6 +106,7 @@ namespace Sass {
for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) { for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) {
l->append(sass_value_to_ast_node(sass_list_get_value(val, i))); l->append(sass_value_to_ast_node(sass_list_get_value(val, i)));
} }
l->is_bracketed(sass_list_get_is_bracketed(val));
return l; return l;
} }
break; break;
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
<ItemGroup Label="LibSass Sources"> <ItemGroup Label="LibSass Sources">
<ClCompile Include="$(LIBSASS_SRC_DIR)\ast.cpp" /> <ClCompile Include="$(LIBSASS_SRC_DIR)\ast.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\memory\SharedPtr.cpp" /> <ClCompile Include="$(LIBSASS_SRC_DIR)\memory\SharedPtr.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\ast_fwd_decl.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\base64vlq.cpp" /> <ClCompile Include="$(LIBSASS_SRC_DIR)\base64vlq.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\bind.cpp" /> <ClCompile Include="$(LIBSASS_SRC_DIR)\bind.cpp" />
<ClCompile Condition="$(VisualStudioVersion) &lt; 14.0" Include="$(LIBSASS_SRC_DIR)\c99func.c" /> <ClCompile Condition="$(VisualStudioVersion) &lt; 14.0" Include="$(LIBSASS_SRC_DIR)\c99func.c" />
......
...@@ -218,6 +218,9 @@ ...@@ -218,6 +218,9 @@
<ClCompile Include="$(LIBSASS_SRC_DIR)\memory\SharedPtr.cpp"> <ClCompile Include="$(LIBSASS_SRC_DIR)\memory\SharedPtr.cpp">
<Filter>Sources</Filter> <Filter>Sources</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(LIBSASS_SRC_DIR)\ast_fwd_decl.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="$(LIBSASS_SRC_DIR)\base64vlq.cpp"> <ClCompile Include="$(LIBSASS_SRC_DIR)\base64vlq.cpp">
<Filter>Sources</Filter> <Filter>Sources</Filter>
</ClCompile> </ClCompile>
......
...@@ -8,6 +8,7 @@ namespace SassTypes ...@@ -8,6 +8,7 @@ namespace SassTypes
Sass_Value* List::construct(const std::vector<v8::Local<v8::Value>> raw_val, Sass_Value **out) { Sass_Value* List::construct(const std::vector<v8::Local<v8::Value>> raw_val, Sass_Value **out) {
size_t length = 0; size_t length = 0;
bool comma = true; bool comma = true;
bool is_bracketed = false;
if (raw_val.size() >= 1) { if (raw_val.size() >= 1) {
if (!raw_val[0]->IsNumber()) { if (!raw_val[0]->IsNumber()) {
...@@ -25,7 +26,7 @@ namespace SassTypes ...@@ -25,7 +26,7 @@ namespace SassTypes
} }
} }
return *out = sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE); return *out = sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE, is_bracketed);
} }
void List::initPrototype(v8::Local<v8::FunctionTemplate> proto) { void List::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
......
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