diff --git a/cli/src/main.rs b/cli/src/main.rs index 347d842d..2bb290eb 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -77,6 +77,10 @@ fn run() -> Result<()> { .long("quiet") .short("q"); + let wasm_arg = Arg::with_name("wasm") + .long("wasm") + .help("compile parsers to wasm instead of native dynamic libraries"); + let matches = App::new("tree-sitter") .author("Max Brunsfeld ") .about("Generates and tests parsers") @@ -125,7 +129,7 @@ fn run() -> Result<()> { .arg(&debug_arg) .arg(&debug_build_arg) .arg(&debug_graph_arg) - .arg(Arg::with_name("wasm").long("wasm").help("use wasm file")) + .arg(&wasm_arg) .arg(Arg::with_name("debug-xml").long("xml").short("x")) .arg( Arg::with_name("stat") @@ -201,7 +205,8 @@ fn run() -> Result<()> { ) .arg(&debug_arg) .arg(&debug_build_arg) - .arg(&debug_graph_arg), + .arg(&debug_graph_arg) + .arg(&wasm_arg), ) .subcommand( SubCommand::with_name("highlight") @@ -308,13 +313,25 @@ fn run() -> Result<()> { let debug_build = matches.is_present("debug-build"); let update = matches.is_present("update"); let filter = matches.value_of("filter"); + let wasm = matches.is_present("wasm"); + let mut parser = Parser::new(); loader.use_debug_build(debug_build); + if wasm { + let engine = tree_sitter::wasmtime::Engine::default(); + parser + .set_wasm_store(WasmStore::new(engine.clone())) + .unwrap(); + loader.use_wasm(engine); + } + let languages = loader.languages_at_path(¤t_dir)?; let language = languages .first() .ok_or_else(|| anyhow!("No language found"))?; + parser.set_language(*language)?; + let test_dir = current_dir.join("test"); // Run the corpus tests. Look for them at two paths: `test/corpus` and `corpus`. @@ -324,7 +341,7 @@ fn run() -> Result<()> { } if test_corpus_dir.is_dir() { test::run_tests_at_path( - *language, + &mut parser, &test_corpus_dir, debug, debug_graph, diff --git a/cli/src/test.rs b/cli/src/test.rs index 69c4a663..1ab57dcf 100644 --- a/cli/src/test.rs +++ b/cli/src/test.rs @@ -55,7 +55,7 @@ impl Default for TestEntry { } pub fn run_tests_at_path( - language: Language, + parser: &mut Parser, path: &Path, debug: bool, debug_graph: bool, @@ -64,11 +64,9 @@ pub fn run_tests_at_path( ) -> Result<()> { let test_entry = parse_tests(path)?; let mut _log_session = None; - let mut parser = Parser::new(); - parser.set_language(language)?; if debug_graph { - _log_session = Some(util::log_graphs(&mut parser, "log.html")?); + _log_session = Some(util::log_graphs(parser, "log.html")?); } else if debug { parser.set_logger(Some(Box::new(|log_type, message| { if log_type == LogType::Lex { @@ -81,7 +79,7 @@ pub fn run_tests_at_path( let mut failures = Vec::new(); let mut corrected_entries = Vec::new(); run_tests( - &mut parser, + parser, test_entry, filter, 0, diff --git a/lib/src/parser.c b/lib/src/parser.c index 12605b37..7e0448ee 100644 --- a/lib/src/parser.c +++ b/lib/src/parser.c @@ -1865,13 +1865,24 @@ const TSLanguage *ts_parser_language(const TSParser *self) { } bool ts_parser_set_language(TSParser *self, const TSLanguage *language) { - if (language) { - if (language->version > TREE_SITTER_LANGUAGE_VERSION) return false; - if (language->version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION) return false; - } ts_parser__external_scanner_destroy(self); + self->language = NULL; + + if (language) { + if ( + language->version > TREE_SITTER_LANGUAGE_VERSION || + language->version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION + ) return false; + + if (ts_language_is_wasm(language)) { + if ( + !self->wasm_store || + !ts_wasm_store_start(self->wasm_store, &self->lexer.data, language) + ) return false; + } + } + self->language = language; - ts_wasm_store_start(self->wasm_store, &self->lexer.data, language); ts_parser__external_scanner_create(self); ts_parser_reset(self); return true; diff --git a/lib/src/wasm.c b/lib/src/wasm.c index c6f320c7..864eb69e 100644 --- a/lib/src/wasm.c +++ b/lib/src/wasm.c @@ -819,11 +819,11 @@ const TSLanguage *ts_wasm_store_load_language( ), .symbol_metadata = copy( &memory[wasm_language.symbol_metadata], - wasm_language.symbol_count * sizeof(TSSymbolMetadata) + (wasm_language.symbol_count + wasm_language.alias_count) * sizeof(TSSymbolMetadata) ), .public_symbol_map = copy( &memory[wasm_language.public_symbol_map], - wasm_language.symbol_count * sizeof(TSSymbol) + (wasm_language.symbol_count + wasm_language.alias_count) * sizeof(TSSymbol) ), .lex_modes = copy( &memory[wasm_language.lex_modes], @@ -884,6 +884,13 @@ const TSLanguage *ts_wasm_store_load_language( ); } + if (language->version >= 14) { + language->primary_state_ids = copy( + &memory[wasm_language.primary_state_ids], + wasm_language.state_count * sizeof(TSStateId) + ); + } + if (language->external_token_count > 0) { language->external_scanner.symbol_map = copy( &memory[wasm_language.external_scanner.symbol_map], @@ -985,8 +992,6 @@ bool ts_wasm_store_add_language( bool ts_wasm_store_start(TSWasmStore *self, TSLexer *lexer, const TSLanguage *language) { uint32_t instance_index; - if (!language) return false; - if (!ts_language_is_wasm(language)) return false; if (!ts_wasm_store_add_language(self, language, &instance_index)) return false; self->current_lexer = lexer; self->current_instance = &self->language_instances.contents[instance_index];