From 88e3907cc08c999f55cf8d01dd4d83953c75ace0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Mar 2019 12:39:04 -0700 Subject: [PATCH] Use QueryPerformanceFrequency as clock on windows --- cli/src/main.rs | 26 +++++++++++++++--------- cli/src/parse.rs | 2 +- lib/binding/bindings.rs | 5 ++--- lib/binding/lib.rs | 4 ++-- lib/include/tree_sitter/api.h | 4 ++-- lib/src/clock.h | 34 +++++++++++++++++++++++++++++++ lib/src/parser.c | 38 +++++++++++++++++------------------ 7 files changed, 76 insertions(+), 37 deletions(-) create mode 100644 lib/src/clock.h diff --git a/cli/src/main.rs b/cli/src/main.rs index 5ad072c6..dc4b5ae6 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -3,7 +3,7 @@ use std::env; use std::fs; use std::path::Path; use std::process::exit; -use std::usize; +use std::{u64, usize}; use tree_sitter_cli::{ config, error, generate, highlight, loader, logger, parse, properties, test, }; @@ -49,6 +49,7 @@ fn run() -> error::Result<()> { .multiple(true) .required(true), ) + .arg(Arg::with_name("scope").long("scope").takes_value(true)) .arg(Arg::with_name("debug").long("debug").short("d")) .arg(Arg::with_name("debug-graph").long("debug-graph").short("D")) .arg(Arg::with_name("quiet").long("quiet").short("q")) @@ -135,7 +136,7 @@ fn run() -> error::Result<()> { let time = matches.is_present("time"); let timeout = matches .value_of("timeout") - .map_or(0, |t| usize::from_str_radix(t, 10).unwrap()); + .map_or(0, |t| u64::from_str_radix(t, 10).unwrap()); loader.find_all_languages(&config.parser_directories)?; let paths = matches .values_of("path") @@ -146,15 +147,20 @@ fn run() -> error::Result<()> { let mut has_error = false; for path in paths { let path = Path::new(path); - let language = - if let Some((l, _)) = loader.language_configuration_for_file_name(path)? { - l - } else if let Some(l) = loader.language_at_path(¤t_dir)? { - l + let language = if let Some(scope) = matches.value_of("scope") { + if let Some(config) = loader.language_configuration_for_scope(scope)? { + config.0 } else { - eprintln!("No language found"); - return Ok(()); - }; + return Err(error::Error(format!("Unknown scope '{}'", scope))); + } + } else if let Some((l, _)) = loader.language_configuration_for_file_name(path)? { + l + } else if let Some(l) = loader.language_at_path(¤t_dir)? { + l + } else { + eprintln!("No language found"); + return Ok(()); + }; has_error |= parse::parse_file_at_path( language, path, diff --git a/cli/src/parse.rs b/cli/src/parse.rs index 27b96c38..f4002233 100644 --- a/cli/src/parse.rs +++ b/cli/src/parse.rs @@ -12,7 +12,7 @@ pub fn parse_file_at_path( max_path_length: usize, quiet: bool, print_time: bool, - timeout: usize, + timeout: u64, debug: bool, debug_graph: bool, ) -> Result { diff --git a/lib/binding/bindings.rs b/lib/binding/bindings.rs index 41999088..7c8c704a 100644 --- a/lib/binding/bindings.rs +++ b/lib/binding/bindings.rs @@ -1,6 +1,5 @@ /* automatically generated by rust-bindgen */ -pub type __darwin_size_t = ::std::os::raw::c_ulong; pub type FILE = [u64; 19usize]; pub type TSSymbol = u16; #[repr(C)] @@ -143,10 +142,10 @@ extern "C" { pub fn ts_parser_set_enabled(arg1: *mut TSParser, arg2: bool); } extern "C" { - pub fn ts_parser_timeout_micros(arg1: *const TSParser) -> usize; + pub fn ts_parser_timeout_micros(arg1: *const TSParser) -> u64; } extern "C" { - pub fn ts_parser_set_timeout_micros(arg1: *mut TSParser, arg2: usize); + pub fn ts_parser_set_timeout_micros(arg1: *mut TSParser, arg2: u64); } extern "C" { pub fn ts_parser_reset(arg1: *mut TSParser); diff --git a/lib/binding/lib.rs b/lib/binding/lib.rs index 9f8f1dec..f4f161a6 100644 --- a/lib/binding/lib.rs +++ b/lib/binding/lib.rs @@ -323,11 +323,11 @@ impl Parser { unsafe { ffi::ts_parser_reset(self.0) } } - pub fn timeout_micros(&self) -> usize { + pub fn timeout_micros(&self) -> u64 { unsafe { ffi::ts_parser_timeout_micros(self.0) } } - pub fn set_timeout_micros(&mut self, timeout_micros: usize) { + pub fn set_timeout_micros(&mut self, timeout_micros: u64) { unsafe { ffi::ts_parser_set_timeout_micros(self.0, timeout_micros) } } diff --git a/lib/include/tree_sitter/api.h b/lib/include/tree_sitter/api.h index 5c72e7b1..e16ca576 100644 --- a/lib/include/tree_sitter/api.h +++ b/lib/include/tree_sitter/api.h @@ -90,8 +90,8 @@ TSTree *ts_parser_parse_string(TSParser *, const TSTree *, const char *, uint32_ TSTree *ts_parser_parse_string_encoding(TSParser *, const TSTree *, const char *, uint32_t, TSInputEncoding); bool ts_parser_enabled(const TSParser *); void ts_parser_set_enabled(TSParser *, bool); -size_t ts_parser_timeout_micros(const TSParser *); -void ts_parser_set_timeout_micros(TSParser *, size_t); +uint64_t ts_parser_timeout_micros(const TSParser *); +void ts_parser_set_timeout_micros(TSParser *, uint64_t); void ts_parser_reset(TSParser *); void ts_parser_set_included_ranges(TSParser *, const TSRange *, uint32_t); const TSRange *ts_parser_included_ranges(const TSParser *, uint32_t *); diff --git a/lib/src/clock.h b/lib/src/clock.h new file mode 100644 index 00000000..3193a6b3 --- /dev/null +++ b/lib/src/clock.h @@ -0,0 +1,34 @@ +#ifndef TREE_SITTER_CLOCK_H_ +#define TREE_SITTER_CLOCK_H_ + +#include + +#ifdef _WIN32 + +#include + +static inline uint64_t get_clock() { + LARGE_INTEGER result; + QueryPerformanceCounter(&result); + return (uint64_t)result.QuadPart; +} + +static inline uint64_t get_clocks_per_second() { + LARGE_INTEGER result; + QueryPerformanceFrequency(&result); + return (uint64_t)result.QuadPart; +} + +#else + +static inline uint64_t get_clock() { + return (uint64_t)clock(); +} + +static inline uint64_t get_clocks_per_second() { + return (uint64_t)CLOCKS_PER_SEC; +} + +#endif + +#endif // TREE_SITTER_CLOCK_H_ diff --git a/lib/src/parser.c b/lib/src/parser.c index 5f850c72..15b33d54 100644 --- a/lib/src/parser.c +++ b/lib/src/parser.c @@ -4,17 +4,18 @@ #include #include #include "tree_sitter/api.h" -#include "./subtree.h" -#include "./lexer.h" -#include "./length.h" -#include "./array.h" -#include "./language.h" #include "./alloc.h" -#include "./stack.h" -#include "./reusable_node.h" -#include "./reduce_action.h" +#include "./array.h" +#include "./clock.h" #include "./error_costs.h" #include "./get_changed_ranges.h" +#include "./language.h" +#include "./length.h" +#include "./lexer.h" +#include "./reduce_action.h" +#include "./reusable_node.h" +#include "./stack.h" +#include "./subtree.h" #include "./tree.h" #define LOG(...) \ @@ -43,7 +44,6 @@ static const unsigned MAX_VERSION_COUNT = 6; static const unsigned MAX_VERSION_COUNT_OVERFLOW = 4; static const unsigned MAX_SUMMARY_DEPTH = 16; static const unsigned MAX_COST_DIFFERENCE = 16 * ERROR_COST_PER_SKIPPED_TREE; -static const unsigned CLOCKS_PER_MICROSECOND = CLOCKS_PER_SEC / 1000000; static const unsigned OP_COUNT_PER_TIMEOUT_CHECK = 100; typedef struct { @@ -66,8 +66,8 @@ struct TSParser { void *external_scanner_payload; FILE *dot_graph_file; unsigned accept_count; - clock_t clock_limit; - clock_t start_clock; + uint64_t clock_limit; + uint64_t start_clock; unsigned operation_count; volatile bool enabled; bool halt_on_error; @@ -1285,7 +1285,7 @@ static bool ts_parser__advance( for (;;) { if (!self->enabled || ++self->operation_count == OP_COUNT_PER_TIMEOUT_CHECK) { self->operation_count = 0; - if (clock() - self->start_clock > self->clock_limit) { + if ((uint64_t)(get_clock() - self->start_clock) > self->clock_limit) { ts_subtree_release(&self->tree_pool, lookahead); return false; } @@ -1509,7 +1509,7 @@ TSParser *ts_parser_new() { self->dot_graph_file = NULL; self->halt_on_error = false; self->enabled = true; - self->clock_limit = SIZE_MAX; + self->clock_limit = UINT64_MAX; self->start_clock = 0; self->operation_count = 0; self->old_tree = NULL_SUBTREE; @@ -1593,13 +1593,13 @@ void ts_parser_set_enabled(TSParser *self, bool enabled) { self->enabled = enabled; } -size_t ts_parser_timeout_micros(const TSParser *self) { - return self->clock_limit / CLOCKS_PER_MICROSECOND; +uint64_t ts_parser_timeout_micros(const TSParser *self) { + return self->clock_limit / (get_clocks_per_second() / 1000000); } -void ts_parser_set_timeout_micros(TSParser *self, size_t timeout_micros) { - self->clock_limit = timeout_micros * CLOCKS_PER_MICROSECOND; - if (self->clock_limit == 0) self->clock_limit = SIZE_MAX; +void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout_micros) { + self->clock_limit = timeout_micros * (get_clocks_per_second() / 1000000); + if (self->clock_limit == 0) self->clock_limit = UINT64_MAX; } void ts_parser_set_included_ranges(TSParser *self, const TSRange *ranges, uint32_t count) { @@ -1663,7 +1663,7 @@ TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input) { uint32_t position = 0, last_position = 0, version_count = 0; self->operation_count = 0; - self->start_clock = clock(); + self->start_clock = get_clock(); do { for (StackVersion version = 0;