mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 06:58:45 +00:00
debug
This commit is contained in:
parent
582ad5668e
commit
0d62ae0814
29 changed files with 99479 additions and 1166 deletions
|
|
@ -8,10 +8,18 @@ find_package(Catch2 2 REQUIRED)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include
|
||||||
include(tree_sitter/api.h)
|
tree-sitter/lib/src
|
||||||
|
tree-sitter/lib/include)
|
||||||
|
|
||||||
|
|
||||||
# add_executable(interpreter_tests tests/tests.cpp)
|
# add_executable(interpreter_tests tests/tests.cpp)
|
||||||
# target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)
|
# target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)
|
||||||
|
|
||||||
# add_executable(lang_interpreter src/main.cpp)
|
add_executable(lang_interpreter src/main.cpp
|
||||||
|
src/visitor.cpp
|
||||||
|
src/build_visitor.cpp
|
||||||
|
src/print_visitor.cpp
|
||||||
|
src/parser.c
|
||||||
|
include/parser.h
|
||||||
|
tree-sitter/lib/src/lib.c)
|
||||||
|
|
|
||||||
|
|
@ -526,6 +526,7 @@ struct AnnotatedType : public Node {
|
||||||
};
|
};
|
||||||
|
|
||||||
using TypeParameter = std::variant<
|
using TypeParameter = std::variant<
|
||||||
|
std::unique_ptr<TypeExpression>,
|
||||||
std::unique_ptr<ParametrizedType>,
|
std::unique_ptr<ParametrizedType>,
|
||||||
std::unique_ptr<Expression>>;
|
std::unique_ptr<Expression>>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
// for clangd
|
// for clangd
|
||||||
#include "tree_sitter/api.h"
|
#include "tree_sitter/api.h"
|
||||||
|
|
||||||
|
extern "C" const TSLanguage* tree_sitter_LANG();
|
||||||
|
|
||||||
namespace parser {
|
namespace parser {
|
||||||
|
|
||||||
|
|
@ -12,31 +13,76 @@ class ParseTree {
|
||||||
public:
|
public:
|
||||||
class Node {
|
class Node {
|
||||||
public:
|
public:
|
||||||
std::string GetType();
|
Node() = default;
|
||||||
std::pair<size_t, size_t> GetStartPoint();
|
Node(const TSNode &node, const std::string* source) : node_(node), source_(source) {}
|
||||||
std::pair<size_t, size_t> GetEndPoint();
|
|
||||||
std::string GetAsSExpression();
|
|
||||||
|
|
||||||
std::string GetValue(); // from source
|
std::string GetType() {
|
||||||
|
return ts_node_type(node_);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsNull();
|
std::pair<size_t, size_t> GetStartPoint() {
|
||||||
bool IsNamed();
|
TSPoint point = ts_node_start_point(node_);
|
||||||
bool IsMissing();
|
return {point.row, point.column};
|
||||||
bool IsExtra(); // comments, etc.
|
}
|
||||||
bool HasError();
|
|
||||||
|
|
||||||
Node NthChild(size_t n);
|
std::pair<size_t, size_t> GetEndPoint() {
|
||||||
size_t ChildCount();
|
TSPoint point = ts_node_end_point(node_);
|
||||||
|
return {point.row, point.column};
|
||||||
|
}
|
||||||
|
|
||||||
Node NthNamedChild(size_t n);
|
std::string GetAsSExpression() {
|
||||||
size_t NamedChildCount();
|
return ts_node_string(node_);
|
||||||
|
}
|
||||||
|
|
||||||
Node ChildByFieldName(const std::string& name);
|
std::string GetValue() { // from source
|
||||||
|
size_t start = ts_node_start_byte(node_);
|
||||||
|
size_t end = ts_node_end_byte(node_);
|
||||||
|
return source_->substr(start, end - start); // TODO check
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNull() {
|
||||||
|
return ts_node_is_null(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNamed() {
|
||||||
|
return ts_node_is_named(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsMissing() {
|
||||||
|
return ts_node_is_missing(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsExtra() { // comments, etc.
|
||||||
|
return ts_node_is_extra(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasError() {
|
||||||
|
return ts_node_has_error(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node NthChild(size_t n) {
|
||||||
|
return Node(ts_node_child(node_, n), source_);
|
||||||
|
}
|
||||||
|
size_t ChildCount() {
|
||||||
|
return ts_node_child_count(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node NthNamedChild(size_t n) {
|
||||||
|
return Node(ts_node_named_child(node_, n), source_);
|
||||||
|
}
|
||||||
|
size_t NamedChildCount() {
|
||||||
|
return ts_node_named_child_count(node_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ChildByFieldName(const std::string& name) {
|
||||||
|
return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()), source_);
|
||||||
|
}
|
||||||
|
|
||||||
// ?? use field id instaed of name ??
|
// ?? use field id instaed of name ??
|
||||||
// ?? node equality check needed ??
|
// ?? node equality check needed ??
|
||||||
private:
|
private:
|
||||||
TSNode node_;
|
TSNode node_;
|
||||||
|
const std::string* source_ = nullptr;
|
||||||
};
|
};
|
||||||
class Cursor { // ?? needed ??
|
class Cursor { // ?? needed ??
|
||||||
public:
|
public:
|
||||||
|
|
@ -54,12 +100,24 @@ public:
|
||||||
TSTreeCursor cursor_;
|
TSTreeCursor cursor_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ParseTree(const std::string& input);
|
ParseTree(const std::string& source) : source_(source) {
|
||||||
|
TSParser* parser = ts_parser_new();
|
||||||
|
ts_parser_set_language(parser, tree_sitter_LANG());
|
||||||
|
|
||||||
|
tree_ = ts_parser_parse_string(
|
||||||
|
parser,
|
||||||
|
NULL,
|
||||||
|
source_.c_str(),
|
||||||
|
source_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Node GetRoot() const {
|
||||||
|
return Node(ts_tree_root_node(tree_), &source_);
|
||||||
|
}
|
||||||
|
|
||||||
Node GetRoot() const;
|
|
||||||
private:
|
private:
|
||||||
TSTree* tree_;
|
TSTree* tree_;
|
||||||
std::string source; // for token value extraction
|
std::string source_; // for token value extraction
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace parser
|
} // namespace parser
|
||||||
|
|
|
||||||
224
include/parser.h
Normal file
224
include/parser.h
Normal file
|
|
@ -0,0 +1,224 @@
|
||||||
|
#ifndef TREE_SITTER_PARSER_H_
|
||||||
|
#define TREE_SITTER_PARSER_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define ts_builtin_sym_error ((TSSymbol)-1)
|
||||||
|
#define ts_builtin_sym_end 0
|
||||||
|
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
typedef uint16_t TSStateId;
|
||||||
|
|
||||||
|
#ifndef TREE_SITTER_API_H_
|
||||||
|
typedef uint16_t TSSymbol;
|
||||||
|
typedef uint16_t TSFieldId;
|
||||||
|
typedef struct TSLanguage TSLanguage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TSFieldId field_id;
|
||||||
|
uint8_t child_index;
|
||||||
|
bool inherited;
|
||||||
|
} TSFieldMapEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t length;
|
||||||
|
} TSFieldMapSlice;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool visible;
|
||||||
|
bool named;
|
||||||
|
bool supertype;
|
||||||
|
} TSSymbolMetadata;
|
||||||
|
|
||||||
|
typedef struct TSLexer TSLexer;
|
||||||
|
|
||||||
|
struct TSLexer {
|
||||||
|
int32_t lookahead;
|
||||||
|
TSSymbol result_symbol;
|
||||||
|
void (*advance)(TSLexer *, bool);
|
||||||
|
void (*mark_end)(TSLexer *);
|
||||||
|
uint32_t (*get_column)(TSLexer *);
|
||||||
|
bool (*is_at_included_range_start)(const TSLexer *);
|
||||||
|
bool (*eof)(const TSLexer *);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TSParseActionTypeShift,
|
||||||
|
TSParseActionTypeReduce,
|
||||||
|
TSParseActionTypeAccept,
|
||||||
|
TSParseActionTypeRecover,
|
||||||
|
} TSParseActionType;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint8_t type;
|
||||||
|
TSStateId state;
|
||||||
|
bool extra;
|
||||||
|
bool repetition;
|
||||||
|
} shift;
|
||||||
|
struct {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t child_count;
|
||||||
|
TSSymbol symbol;
|
||||||
|
int16_t dynamic_precedence;
|
||||||
|
uint16_t production_id;
|
||||||
|
} reduce;
|
||||||
|
uint8_t type;
|
||||||
|
} TSParseAction;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t lex_state;
|
||||||
|
uint16_t external_lex_state;
|
||||||
|
} TSLexMode;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
TSParseAction action;
|
||||||
|
struct {
|
||||||
|
uint8_t count;
|
||||||
|
bool reusable;
|
||||||
|
} entry;
|
||||||
|
} TSParseActionEntry;
|
||||||
|
|
||||||
|
struct TSLanguage {
|
||||||
|
uint32_t version;
|
||||||
|
uint32_t symbol_count;
|
||||||
|
uint32_t alias_count;
|
||||||
|
uint32_t token_count;
|
||||||
|
uint32_t external_token_count;
|
||||||
|
uint32_t state_count;
|
||||||
|
uint32_t large_state_count;
|
||||||
|
uint32_t production_id_count;
|
||||||
|
uint32_t field_count;
|
||||||
|
uint16_t max_alias_sequence_length;
|
||||||
|
const uint16_t *parse_table;
|
||||||
|
const uint16_t *small_parse_table;
|
||||||
|
const uint32_t *small_parse_table_map;
|
||||||
|
const TSParseActionEntry *parse_actions;
|
||||||
|
const char * const *symbol_names;
|
||||||
|
const char * const *field_names;
|
||||||
|
const TSFieldMapSlice *field_map_slices;
|
||||||
|
const TSFieldMapEntry *field_map_entries;
|
||||||
|
const TSSymbolMetadata *symbol_metadata;
|
||||||
|
const TSSymbol *public_symbol_map;
|
||||||
|
const uint16_t *alias_map;
|
||||||
|
const TSSymbol *alias_sequences;
|
||||||
|
const TSLexMode *lex_modes;
|
||||||
|
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||||
|
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||||
|
TSSymbol keyword_capture_token;
|
||||||
|
struct {
|
||||||
|
const bool *states;
|
||||||
|
const TSSymbol *symbol_map;
|
||||||
|
void *(*create)(void);
|
||||||
|
void (*destroy)(void *);
|
||||||
|
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
|
||||||
|
unsigned (*serialize)(void *, char *);
|
||||||
|
void (*deserialize)(void *, const char *, unsigned);
|
||||||
|
} external_scanner;
|
||||||
|
const TSStateId *primary_state_ids;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lexer Macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define START_LEXER() \
|
||||||
|
bool result = false; \
|
||||||
|
bool skip = false; \
|
||||||
|
bool eof = false; \
|
||||||
|
int32_t lookahead; \
|
||||||
|
goto start; \
|
||||||
|
next_state: \
|
||||||
|
lexer->advance(lexer, skip); \
|
||||||
|
start: \
|
||||||
|
skip = false; \
|
||||||
|
lookahead = lexer->lookahead;
|
||||||
|
|
||||||
|
#define ADVANCE(state_value) \
|
||||||
|
{ \
|
||||||
|
state = state_value; \
|
||||||
|
goto next_state; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKIP(state_value) \
|
||||||
|
{ \
|
||||||
|
skip = true; \
|
||||||
|
state = state_value; \
|
||||||
|
goto next_state; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ACCEPT_TOKEN(symbol_value) \
|
||||||
|
result = true; \
|
||||||
|
lexer->result_symbol = symbol_value; \
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
|
||||||
|
#define END_STATE() return result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse Table Macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
|
||||||
|
|
||||||
|
#define STATE(id) id
|
||||||
|
|
||||||
|
#define ACTIONS(id) id
|
||||||
|
|
||||||
|
#define SHIFT(state_value) \
|
||||||
|
{{ \
|
||||||
|
.shift = { \
|
||||||
|
.type = TSParseActionTypeShift, \
|
||||||
|
.state = state_value \
|
||||||
|
} \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define SHIFT_REPEAT(state_value) \
|
||||||
|
{{ \
|
||||||
|
.shift = { \
|
||||||
|
.type = TSParseActionTypeShift, \
|
||||||
|
.state = state_value, \
|
||||||
|
.repetition = true \
|
||||||
|
} \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define SHIFT_EXTRA() \
|
||||||
|
{{ \
|
||||||
|
.shift = { \
|
||||||
|
.type = TSParseActionTypeShift, \
|
||||||
|
.extra = true \
|
||||||
|
} \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define REDUCE(symbol_val, child_count_val, ...) \
|
||||||
|
{{ \
|
||||||
|
.reduce = { \
|
||||||
|
.type = TSParseActionTypeReduce, \
|
||||||
|
.symbol = symbol_val, \
|
||||||
|
.child_count = child_count_val, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
}, \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define RECOVER() \
|
||||||
|
{{ \
|
||||||
|
.type = TSParseActionTypeRecover \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define ACCEPT_INPUT() \
|
||||||
|
{{ \
|
||||||
|
.type = TSParseActionTypeAccept \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TREE_SITTER_PARSER_H_
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
// forclangd
|
// forclangd
|
||||||
#include "../include/build_visitor.hpp"
|
#include "../include/build_visitor.hpp"
|
||||||
#include "../include/parse_token_types.hpp"
|
#include "../include/parse_token_types.hpp"
|
||||||
#include <bits/utility.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace interpreter {
|
namespace interpreter {
|
||||||
|
|
||||||
|
|
@ -77,6 +79,7 @@ void BuildVisitor::Visit(Namespace* node) {
|
||||||
auto current_node_ = parse_node.ChildByFieldName("name");
|
auto current_node_ = parse_node.ChildByFieldName("name");
|
||||||
|
|
||||||
auto current_node_type = current_node_.GetType();
|
auto current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
if (current_node_type == parser::tokens::DefinedAnnotatedName) {
|
if (current_node_type == parser::tokens::DefinedAnnotatedName) {
|
||||||
std::string name_modifier = parse_node.NthChild(1).GetValue(); // TODO
|
std::string name_modifier = parse_node.NthChild(1).GetValue(); // TODO
|
||||||
if (name_modifier == "const") {
|
if (name_modifier == "const") {
|
||||||
|
|
@ -254,10 +257,11 @@ void BuildVisitor::Visit(TypeclassDefinition* node) {
|
||||||
size_t child_count = parse_node.NamedChildCount();
|
size_t child_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
if (child_count > 1) {
|
if (child_count > 1) {
|
||||||
node->requirements.resize(child_count - 1, std::make_unique<FunctionDeclaration>());
|
node->requirements.resize(child_count - 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < child_count - 1; ++i) {
|
for (size_t i = 0; i < child_count - 1; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i + 1);
|
current_node_ = parse_node.NthNamedChild(i + 1);
|
||||||
|
node->requirements[i] = std::make_unique<FunctionDeclaration>();
|
||||||
Visit(node->requirements[i].get());
|
Visit(node->requirements[i].get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -463,12 +467,23 @@ void BuildVisitor::Visit(DefinitionParameter* node) {
|
||||||
size_t child_count = parse_node.NamedChildCount();
|
size_t child_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
if (child_count > 1) {
|
if (child_count > 1) {
|
||||||
node->typeclasses.resize(child_count - 1, std::make_unique<ParametrizedTypeclass>());
|
node->typeclasses.resize(child_count - 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < child_count - 1; ++i) {
|
for (size_t i = 0; i < child_count - 1; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i + 1);
|
current_node_ = parse_node.NthNamedChild(i + 1);
|
||||||
Visit(node->typeclasses[i].get());
|
|
||||||
// choose between typeclass_expression and parametrized_typeclass
|
std::string current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
|
node->typeclasses[i] = std::make_unique<ParametrizedTypeclass>();
|
||||||
|
|
||||||
|
if (current_node_type == parser::tokens::TypeclassExpression) { // optimize ??
|
||||||
|
node->typeclasses[i]->typeclass_expression = std::make_unique<TypeclassExpression>();
|
||||||
|
Visit(node->typeclasses[i]->typeclass_expression.get());
|
||||||
|
} else if (current_node_type == parser::tokens::ParametrizedTypeclass) {
|
||||||
|
Visit(node->typeclasses[i].get());
|
||||||
|
} else {
|
||||||
|
// error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,12 +498,23 @@ void BuildVisitor::Visit(DefinitionArgument* node) {
|
||||||
size_t child_count = parse_node.NamedChildCount();
|
size_t child_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
if (child_count > 1) {
|
if (child_count > 1) {
|
||||||
node->types.resize(child_count - 1, std::make_unique<ParametrizedType>());
|
node->types.resize(child_count - 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < child_count - 1; ++i) {
|
for (size_t i = 0; i < child_count - 1; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i + 1);
|
current_node_ = parse_node.NthNamedChild(i + 1);
|
||||||
Visit(node->types[i].get());
|
|
||||||
// choose between type_expression and parametrized_type
|
std::string current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
|
node->types[i] = std::make_unique<ParametrizedType>();
|
||||||
|
|
||||||
|
if (current_node_type == parser::tokens::TypeExpression) { // optimize ??
|
||||||
|
node->types[i]->type_expression = std::make_unique<TypeExpression>();
|
||||||
|
Visit(node->types[i]->type_expression.get());
|
||||||
|
} else if (current_node_type == parser::tokens::ParametrizedType) {
|
||||||
|
Visit(node->types[i].get());
|
||||||
|
} else {
|
||||||
|
// error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1079,10 +1105,11 @@ void BuildVisitor::Visit(TupleName* node) {
|
||||||
|
|
||||||
size_t names_count = parse_node.NamedChildCount();
|
size_t names_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
node->names.resize(names_count, std::make_unique<AnnotatedName>());
|
node->names.resize(names_count);
|
||||||
|
|
||||||
for (size_t i = 0; i < names_count; ++i) {
|
for (size_t i = 0; i < names_count; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i);
|
current_node_ = parse_node.NthNamedChild(i);
|
||||||
|
node->names[i] = std::make_unique<AnnotatedName>();
|
||||||
Visit(node->names[i].get());
|
Visit(node->names[i].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1094,10 +1121,11 @@ void BuildVisitor::Visit(VariantName* node) {
|
||||||
|
|
||||||
size_t names_count = parse_node.NamedChildCount();
|
size_t names_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
node->names.resize(names_count, std::make_unique<AnnotatedName>());
|
node->names.resize(names_count);
|
||||||
|
|
||||||
for (size_t i = 0; i < names_count; ++i) {
|
for (size_t i = 0; i < names_count; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i);
|
current_node_ = parse_node.NthNamedChild(i);
|
||||||
|
node->names[i] =std::make_unique<AnnotatedName>();
|
||||||
Visit(node->names[i].get());
|
Visit(node->names[i].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1109,7 +1137,7 @@ void BuildVisitor::Visit(AnnotatedName* node) {
|
||||||
|
|
||||||
node->name = parse_node.ChildByFieldName("name").GetValue();
|
node->name = parse_node.ChildByFieldName("name").GetValue();
|
||||||
|
|
||||||
if (parse_node.ChildCount() > 1) {
|
if (parse_node.NamedChildCount() > 1) {
|
||||||
current_node_ = parse_node.ChildByFieldName("type");
|
current_node_ = parse_node.ChildByFieldName("type");
|
||||||
node->type = std::make_unique<ParametrizedType>();
|
node->type = std::make_unique<ParametrizedType>();
|
||||||
Visit(node->type.value().get());
|
Visit(node->type.value().get());
|
||||||
|
|
@ -1144,27 +1172,27 @@ void BuildVisitor::Visit(AnyName& node) {
|
||||||
// Type
|
// Type
|
||||||
|
|
||||||
void BuildVisitor::Visit(TypeConstructor* node) {
|
void BuildVisitor::Visit(TypeConstructor* node) {
|
||||||
auto parse_node = current_node_;
|
// auto parse_node = current_node_;
|
||||||
|
//
|
||||||
current_node_ = parse_node.ChildByFieldName("type");
|
// current_node_ = parse_node.ChildByFieldName("type");
|
||||||
node->type = std::make_unique<ParametrizedType>();
|
// node->type = std::make_unique<ParametrizedType>();
|
||||||
Visit(node->type.get());
|
// Visit(node->type.get());
|
||||||
|
//
|
||||||
size_t parameter_count = (parse_node.NamedChildCount() - 1) / 2;
|
// size_t parameter_count = (parse_node.NamedChildCount() - 1) / 2;
|
||||||
|
//
|
||||||
node->parameters.resize(parameter_count);
|
// node->parameters.resize(parameter_count);
|
||||||
|
//
|
||||||
for (size_t i = 0; i < parameter_count * 2; ++i) {
|
// for (size_t i = 0; i < parameter_count * 2; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i + 1);
|
// current_node_ = parse_node.NthNamedChild(i + 1);
|
||||||
|
//
|
||||||
if (i % 2 == 0) {
|
// if (i % 2 == 0) {
|
||||||
node->parameters[i / 2].first = current_node_.GetValue();
|
// node->parameters[i / 2].first = current_node_.GetValue();
|
||||||
} else {
|
// } else {
|
||||||
Visit(node->parameters[i / 2].second);
|
// Visit(node->parameters[i / 2].second);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
current_node_ = parse_node;
|
// current_node_ = parse_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildVisitor::Visit(TupleType* node) {
|
void BuildVisitor::Visit(TupleType* node) {
|
||||||
|
|
@ -1245,11 +1273,23 @@ void BuildVisitor::Visit(AnnotatedType* node) {
|
||||||
size_t child_count = parse_node.NamedChildCount();
|
size_t child_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
if (child_count > 1) {
|
if (child_count > 1) {
|
||||||
node->annotations.resize(child_count - 1, std::make_unique<ParametrizedTypeclass>());
|
node->annotations.resize(child_count - 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < child_count - 1; ++i) {
|
for (size_t i = 0; i < child_count - 1; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i + 1);
|
current_node_ = parse_node.NthNamedChild(i + 1);
|
||||||
|
|
||||||
|
std::string current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
|
node->annotations[i] = std::make_unique<ParametrizedTypeclass>();
|
||||||
|
|
||||||
|
if (current_node_type == parser::tokens::TypeclassExpression) { // optimize ??
|
||||||
|
node->annotations[i]->typeclass_expression = std::make_unique<TypeclassExpression>();
|
||||||
|
Visit(node->annotations[i]->typeclass_expression.get());
|
||||||
|
} else if (current_node_type == parser::tokens::ParametrizedTypeclass) {
|
||||||
Visit(node->annotations[i].get());
|
Visit(node->annotations[i].get());
|
||||||
|
} else {
|
||||||
|
// error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1296,7 +1336,7 @@ void BuildVisitor::Visit(TypeExpression* node) {
|
||||||
current_node_ = parse_node;
|
current_node_ = parse_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildVisitor::Visit(AnyType& node) {
|
void BuildVisitor::Visit(AnyType& node) { // Or ScopedAnyType
|
||||||
auto parse_node = current_node_;
|
auto parse_node = current_node_;
|
||||||
|
|
||||||
current_node_ = parse_node.NthNamedChild(0);
|
current_node_ = parse_node.NthNamedChild(0);
|
||||||
|
|
@ -1349,7 +1389,10 @@ void BuildVisitor::Visit(TypeParameter& node) {
|
||||||
|
|
||||||
std::string current_node_type = current_node_.GetType();
|
std::string current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
if (current_node_type == parser::tokens::ParametrizedType) { // optimize ??
|
if (current_node_type == parser::tokens::TypeExpression) { // optimize ??
|
||||||
|
node = std::make_unique<TypeExpression>();
|
||||||
|
Visit(std::get<std::unique_ptr<TypeExpression>>(node).get());
|
||||||
|
} else if (current_node_type == parser::tokens::ParametrizedType) {
|
||||||
node = std::make_unique<ParametrizedType>();
|
node = std::make_unique<ParametrizedType>();
|
||||||
Visit(std::get<std::unique_ptr<ParametrizedType>>(node).get());
|
Visit(std::get<std::unique_ptr<ParametrizedType>>(node).get());
|
||||||
} else if (current_node_type == parser::tokens::Expression) {
|
} else if (current_node_type == parser::tokens::Expression) {
|
||||||
|
|
@ -1374,11 +1417,23 @@ void BuildVisitor::Visit(AnnotatedTypeclass* node) {
|
||||||
size_t child_count = parse_node.NamedChildCount();
|
size_t child_count = parse_node.NamedChildCount();
|
||||||
|
|
||||||
if (child_count > 1) {
|
if (child_count > 1) {
|
||||||
node->annotations.resize(child_count - 1, std::make_unique<ParametrizedTypeclass>());
|
node->annotations.resize(child_count - 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < child_count - 1; ++i) {
|
for (size_t i = 0; i < child_count - 1; ++i) {
|
||||||
current_node_ = parse_node.NthNamedChild(i + 1);
|
current_node_ = parse_node.NthNamedChild(i + 1);
|
||||||
Visit(node->annotations[i].get());
|
|
||||||
|
std::string current_node_type = current_node_.GetType();
|
||||||
|
|
||||||
|
node->annotations[i] = std::make_unique<ParametrizedTypeclass>();
|
||||||
|
|
||||||
|
if (current_node_type == parser::tokens::TypeclassExpression) { // optimize ??
|
||||||
|
node->annotations[i]->typeclass_expression = std::make_unique<TypeclassExpression>();
|
||||||
|
Visit(node->annotations[i]->typeclass_expression.get());
|
||||||
|
} else if (current_node_type == parser::tokens::ParametrizedTypeclass) {
|
||||||
|
Visit(node->annotations[i].get());
|
||||||
|
} else {
|
||||||
|
// error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
40
src/main.cpp
Normal file
40
src/main.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// for clangd
|
||||||
|
#include "../include/parse_tree.hpp"
|
||||||
|
#include "../include/interpreter_tree.hpp"
|
||||||
|
#include "../include/build_visitor.hpp"
|
||||||
|
#include "../include/print_visitor.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char** argv) { // TODO, only test version
|
||||||
|
if (argc < 2 || argc > 2) {
|
||||||
|
std::cout << "Wrong argument count (provide one argument - source file)\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filename = argv[1];
|
||||||
|
|
||||||
|
std::ifstream in;
|
||||||
|
in.open(filename); // TODO handle errors
|
||||||
|
|
||||||
|
std::stringstream source_stream;
|
||||||
|
|
||||||
|
source_stream << in.rdbuf();
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
std::string source = source_stream.str();
|
||||||
|
|
||||||
|
parser::ParseTree parse_tree(source);
|
||||||
|
|
||||||
|
std::unique_ptr<interpreter::tokens::SourceFile> source_file =
|
||||||
|
std::make_unique<interpreter::tokens::SourceFile>();
|
||||||
|
|
||||||
|
interpreter::BuildVisitor build_visitor(parse_tree);
|
||||||
|
interpreter::PrintVisitor print_visitor(std::cout);
|
||||||
|
|
||||||
|
build_visitor.VisitSourceFile(source_file.get());
|
||||||
|
//print_visitor.VisitSourceFile(source_file.get());
|
||||||
|
}
|
||||||
12
src/node.cpp
12
src/node.cpp
|
|
@ -1,12 +0,0 @@
|
||||||
// for clangd
|
|
||||||
#include "../include/node.hpp"
|
|
||||||
#include "../include/visitor.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace interpreter {
|
|
||||||
|
|
||||||
/*void Node::Accept(Visitor* visitor) {
|
|
||||||
visitor->Visit(this);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
} // namespace interpreter
|
|
||||||
98452
src/parser.c
Normal file
98452
src/parser.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -9,7 +9,7 @@ void PrintVisitor::Visit(Node* node) {
|
||||||
|
|
||||||
// Sources -----------------
|
// Sources -----------------
|
||||||
void PrintVisitor::Visit(SourceFile* node) {
|
void PrintVisitor::Visit(SourceFile* node) {
|
||||||
out_ << "<SourceFile>\n\n";
|
out_ << "(SourceFile\n\n";
|
||||||
for (auto& statement : node->statements) {
|
for (auto& statement : node->statements) {
|
||||||
if (std::holds_alternative<Partition>(statement)) {
|
if (std::holds_alternative<Partition>(statement)) {
|
||||||
Visit(&std::get<Partition>(statement));
|
Visit(&std::get<Partition>(statement));
|
||||||
|
|
@ -19,21 +19,21 @@ void PrintVisitor::Visit(SourceFile* node) {
|
||||||
// error
|
// error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_ << "\n<SourceFile/>";
|
out_ << "\nSourceFile)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(Sources* node) {
|
void PrintVisitor::Visit(Sources* node) {
|
||||||
out_ << "<Sources>\n\n";
|
out_ << "(Sources\n\n";
|
||||||
for (auto& statement : node->statements) {
|
for (auto& statement : node->statements) {
|
||||||
Visitor::Visit(statement);
|
Visitor::Visit(statement);
|
||||||
}
|
}
|
||||||
out_ << "\n</Sources>";
|
out_ << "\n)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespaces, partittions -----------------
|
// Namespaces, partittions -----------------
|
||||||
|
|
||||||
void PrintVisitor::Visit(Partition* node) {
|
void PrintVisitor::Visit(Partition* node) {
|
||||||
out_ << "<Partition> ";
|
out_ << "(Partition ";
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case Partition::Test:
|
case Partition::Test:
|
||||||
out_ << "TEST";
|
out_ << "TEST";
|
||||||
|
|
@ -56,11 +56,11 @@ void PrintVisitor::Visit(Partition* node) {
|
||||||
}
|
}
|
||||||
out_ << " {\n";
|
out_ << " {\n";
|
||||||
Visit(node->scope.get());
|
Visit(node->scope.get());
|
||||||
out_ << "} </Partition>\n";
|
out_ << "} )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(Namespace* node) {
|
void PrintVisitor::Visit(Namespace* node) {
|
||||||
out_ << "<Namespace> ";
|
out_ << "(Namespace ";
|
||||||
if (std::holds_alternative<std::unique_ptr<DefinedAnnotatedName>>(node->name)) {
|
if (std::holds_alternative<std::unique_ptr<DefinedAnnotatedName>>(node->name)) {
|
||||||
if (node->is_const) {
|
if (node->is_const) {
|
||||||
out_ << "const ";
|
out_ << "const ";
|
||||||
|
|
@ -75,13 +75,13 @@ void PrintVisitor::Visit(Namespace* node) {
|
||||||
}
|
}
|
||||||
out_ << "{\n";
|
out_ << "{\n";
|
||||||
Visit(node->scope.get());
|
Visit(node->scope.get());
|
||||||
out_ << "} </Namespace>\n";
|
out_ << "} )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definitions -----------------
|
// Definitions -----------------
|
||||||
|
|
||||||
void PrintVisitor::Visit(ImportStatement* node) {
|
void PrintVisitor::Visit(ImportStatement* node) {
|
||||||
out_ << "<Import> \"" << node->module_name << "\" ";
|
out_ << "(Import \"" << node->module_name << "\" ";
|
||||||
if (node->symbols.size() > 0) {
|
if (node->symbols.size() > 0) {
|
||||||
out_ << '\n';
|
out_ << '\n';
|
||||||
}
|
}
|
||||||
|
|
@ -89,35 +89,35 @@ void PrintVisitor::Visit(ImportStatement* node) {
|
||||||
Visitor::Visit(symbol);
|
Visitor::Visit(symbol);
|
||||||
out_ << '\n';
|
out_ << '\n';
|
||||||
}
|
}
|
||||||
out_ << "</Import>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(UsageDefinition* node) {
|
void PrintVisitor::Visit(UsageDefinition* node) {
|
||||||
out_ << "<Usage> ";
|
out_ << "(Usage ";
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
out_ << " = ";
|
out_ << " = ";
|
||||||
Visit(node->import_statement.get());
|
Visit(node->import_statement.get());
|
||||||
out_ << "</Usage>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(AliasDefinition* node) {
|
void PrintVisitor::Visit(AliasDefinition* node) {
|
||||||
out_ << "<Alias> ";
|
out_ << "(Alias ";
|
||||||
Visit(node->type.get());
|
Visit(node->type.get());
|
||||||
out_ << " = ";
|
out_ << " = ";
|
||||||
Visit(node->value.get());
|
Visit(node->value.get());
|
||||||
out_ << "</Alias>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(VariableDefinition* node) {
|
void PrintVisitor::Visit(VariableDefinition* node) {
|
||||||
out_ << "<Variable> " << (node->is_const ? "const" : "var") << ' ';
|
out_ << "(Variable " << (node->is_const ? "const" : "var") << ' ';
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
out_ << " = ";
|
out_ << " = ";
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
out_ << "</Variable>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(FunctionDeclaration* node) {
|
void PrintVisitor::Visit(FunctionDeclaration* node) {
|
||||||
out_ << "<FunctionDeclaration> ";
|
out_ << "(FunctionDeclaration ";
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
out_ << "\n";
|
out_ << "\n";
|
||||||
for (auto& parameter : node->parameters) {
|
for (auto& parameter : node->parameters) {
|
||||||
|
|
@ -127,35 +127,35 @@ void PrintVisitor::Visit(FunctionDeclaration* node) {
|
||||||
for (auto& argument_type : node->argument_types) {
|
for (auto& argument_type : node->argument_types) {
|
||||||
Visitor::Visit(argument_type);
|
Visitor::Visit(argument_type);
|
||||||
}
|
}
|
||||||
out_ << "</FunctionDeclaration>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(FunctionDefinition* node) {
|
void PrintVisitor::Visit(FunctionDefinition* node) {
|
||||||
out_ << "<Function> ";
|
out_ << "(Function ";
|
||||||
Visit(node->name.get());
|
Visit(node->name.get());
|
||||||
out_ << " = ";
|
out_ << " = ";
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
out_ << "</Function>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(AliasTypeDefinition* node) {
|
void PrintVisitor::Visit(AliasTypeDefinition* node) {
|
||||||
out_ << "<AliasType> ";
|
out_ << "(AliasType ";
|
||||||
Visit(node->type.get());
|
Visit(node->type.get());
|
||||||
out_ << " = ";
|
out_ << " = ";
|
||||||
Visit(node->value.get());
|
Visit(node->value.get());
|
||||||
out_ << "</AliasType>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TypeDefinition* node) {
|
void PrintVisitor::Visit(TypeDefinition* node) {
|
||||||
out_ << "<Type> ";
|
out_ << "(Type ";
|
||||||
Visit(node->type.get());
|
Visit(node->type.get());
|
||||||
out_ << " = ";
|
out_ << " = ";
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
out_ << "</Type>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TypeclassDefinition* node) {
|
void PrintVisitor::Visit(TypeclassDefinition* node) {
|
||||||
out_ << "<Typeclass> ";
|
out_ << "(Typeclass ";
|
||||||
Visit(node->typeclass.get());
|
Visit(node->typeclass.get());
|
||||||
if (node->requirements.size() > 0) {
|
if (node->requirements.size() > 0) {
|
||||||
out_ << " : \n";
|
out_ << " : \n";
|
||||||
|
|
@ -164,13 +164,13 @@ void PrintVisitor::Visit(TypeclassDefinition* node) {
|
||||||
out_ << "& ";
|
out_ << "& ";
|
||||||
Visit(requirement.get());
|
Visit(requirement.get());
|
||||||
}
|
}
|
||||||
out_ << "</Typeclass>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definition parts
|
// Definition parts
|
||||||
|
|
||||||
void PrintVisitor::Visit(DefinedName* node) {
|
void PrintVisitor::Visit(DefinedName* node) {
|
||||||
out_ << "<DefinedName> ";
|
out_ << "(DefinedName ";
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
if (node->parameters.size() > 0) {
|
if (node->parameters.size() > 0) {
|
||||||
out_ << "\n";
|
out_ << "\n";
|
||||||
|
|
@ -184,11 +184,11 @@ void PrintVisitor::Visit(DefinedName* node) {
|
||||||
for (auto& argument : node->arguments) {
|
for (auto& argument : node->arguments) {
|
||||||
Visit(argument.get());
|
Visit(argument.get());
|
||||||
}
|
}
|
||||||
out_ << "</DefinedName>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(DefinedAnnotatedName* node) {
|
void PrintVisitor::Visit(DefinedAnnotatedName* node) {
|
||||||
out_ << "<DefinedAnnotatedName> ";
|
out_ << "(DefinedAnnotatedName ";
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
out_ << " : ";
|
out_ << " : ";
|
||||||
if (std::holds_alternative<std::unique_ptr<DefinedType>>(node->type)) {
|
if (std::holds_alternative<std::unique_ptr<DefinedType>>(node->type)) {
|
||||||
|
|
@ -198,11 +198,11 @@ void PrintVisitor::Visit(DefinedAnnotatedName* node) {
|
||||||
} else {
|
} else {
|
||||||
// no annotation
|
// no annotation
|
||||||
}
|
}
|
||||||
out_ << " </DefinedAnnotatedName>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(DefinedType* node) {
|
void PrintVisitor::Visit(DefinedType* node) {
|
||||||
out_ << "<DefinedType> ";
|
out_ << "(DefinedType ";
|
||||||
Visit(node->type.get());
|
Visit(node->type.get());
|
||||||
if (node->parameters.size() > 0) {
|
if (node->parameters.size() > 0) {
|
||||||
out_ << "\n";
|
out_ << "\n";
|
||||||
|
|
@ -216,11 +216,11 @@ void PrintVisitor::Visit(DefinedType* node) {
|
||||||
for (auto& argument : node->arguments) {
|
for (auto& argument : node->arguments) {
|
||||||
Visit(argument.get());
|
Visit(argument.get());
|
||||||
}
|
}
|
||||||
out_ << "</DefinedType>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(DefinedTypeclass* node) {
|
void PrintVisitor::Visit(DefinedTypeclass* node) {
|
||||||
out_ << "<DefinedTypeclass> ";
|
out_ << "(DefinedTypeclass ";
|
||||||
Visit(node->typeclass.get());
|
Visit(node->typeclass.get());
|
||||||
if (node->parameters.size() > 0) {
|
if (node->parameters.size() > 0) {
|
||||||
out_ << "\n";
|
out_ << "\n";
|
||||||
|
|
@ -234,33 +234,33 @@ void PrintVisitor::Visit(DefinedTypeclass* node) {
|
||||||
for (auto& argument : node->arguments) {
|
for (auto& argument : node->arguments) {
|
||||||
Visit(argument.get());
|
Visit(argument.get());
|
||||||
}
|
}
|
||||||
out_ << "</DefinedTypeclass>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(DefinitionParameter* node) {
|
void PrintVisitor::Visit(DefinitionParameter* node) {
|
||||||
out_ << "<DefinitionParameter> " << (node->typeclasses.size() > 0 ? "(" : "");
|
out_ << "(DefinitionParameter " << (node->typeclasses.size() > 0 ? "(" : "");
|
||||||
Visit(&node->type);
|
Visit(&node->type);
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
for (auto& typeclass : node->typeclasses) {
|
for (auto& typeclass : node->typeclasses) {
|
||||||
Visit(typeclass.get());
|
Visit(typeclass.get());
|
||||||
}
|
}
|
||||||
out_ << "</DefinitionParamater>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(DefinitionArgument* node) {
|
void PrintVisitor::Visit(DefinitionArgument* node) {
|
||||||
out_ << "<DefinitionArgument> " << (node->types.size() > 0 ? "(" : "");
|
out_ << "(DefinitionArgument " << (node->types.size() > 0 ? "(" : "");
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
for (auto& type : node->types) {
|
for (auto& type : node->types) {
|
||||||
Visit(type.get());
|
Visit(type.get());
|
||||||
}
|
}
|
||||||
out_ << "</DefinitionArgument>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flow control -----------------
|
// Flow control -----------------
|
||||||
|
|
||||||
void PrintVisitor::Visit(MatchCase* node) {
|
void PrintVisitor::Visit(MatchCase* node) {
|
||||||
out_ << "<MatchCase> | ";
|
out_ << "(MatchCase | ";
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
if (node->condition.has_value()) {
|
if (node->condition.has_value()) {
|
||||||
out_ << " ? ";
|
out_ << " ? ";
|
||||||
|
|
@ -270,21 +270,21 @@ void PrintVisitor::Visit(MatchCase* node) {
|
||||||
out_ << " -> ";
|
out_ << " -> ";
|
||||||
Visitor::Visit(node->statement.value());
|
Visitor::Visit(node->statement.value());
|
||||||
}
|
}
|
||||||
out_ << "</MatchCase>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(Match* node) {
|
void PrintVisitor::Visit(Match* node) {
|
||||||
out_ << "<Match> ";
|
out_ << "(Match ";
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
out_ << " with\n";
|
out_ << " with\n";
|
||||||
for (auto& match_case : node->matches) {
|
for (auto& match_case : node->matches) {
|
||||||
Visit(&match_case);
|
Visit(&match_case);
|
||||||
}
|
}
|
||||||
out_ << "</Match>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(Condition* node) {
|
void PrintVisitor::Visit(Condition* node) {
|
||||||
out_ << "<If> ";
|
out_ << "(If ";
|
||||||
Visitor::Visit(node->conditions[0]);
|
Visitor::Visit(node->conditions[0]);
|
||||||
out_ << " then\n";
|
out_ << " then\n";
|
||||||
Visitor::Visit(node->statements[0]);
|
Visitor::Visit(node->statements[0]);
|
||||||
|
|
@ -301,63 +301,63 @@ void PrintVisitor::Visit(Condition* node) {
|
||||||
Visitor::Visit(node->statements[node->conditions.size()]);
|
Visitor::Visit(node->statements[node->conditions.size()]);
|
||||||
out_ << '\n';
|
out_ << '\n';
|
||||||
}
|
}
|
||||||
out_ << "</If>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(DoWhileLoop* node) {
|
void PrintVisitor::Visit(DoWhileLoop* node) {
|
||||||
out_ << "<DoWhile>\n";
|
out_ << "(DoWhile\n";
|
||||||
Visitor::Visit(node->statement);
|
Visitor::Visit(node->statement);
|
||||||
out_ << "\nwhile\n";
|
out_ << "\nwhile\n";
|
||||||
Visitor::Visit(node->condition);
|
Visitor::Visit(node->condition);
|
||||||
out_ << "\n</DoWhile>\n";
|
out_ << "\n)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(WhileLoop* node) {
|
void PrintVisitor::Visit(WhileLoop* node) {
|
||||||
out_ << "<While>\n";
|
out_ << "(While\n";
|
||||||
Visitor::Visit(node->statement);
|
Visitor::Visit(node->statement);
|
||||||
out_ << "\ndo\n";
|
out_ << "\ndo\n";
|
||||||
Visitor::Visit(node->condition);
|
Visitor::Visit(node->condition);
|
||||||
out_ << "\n</While>\n";
|
out_ << "\n)\n";
|
||||||
}
|
}
|
||||||
void PrintVisitor::Visit(ForLoop* node) {
|
void PrintVisitor::Visit(ForLoop* node) {
|
||||||
out_ << "<For>\n";
|
out_ << "(For\n";
|
||||||
Visitor::Visit(node->variable);
|
Visitor::Visit(node->variable);
|
||||||
out_ << "\nin\n";
|
out_ << "\nin\n";
|
||||||
Visitor::Visit(node->interval);
|
Visitor::Visit(node->interval);
|
||||||
out_ << "\ndo\n";
|
out_ << "\ndo\n";
|
||||||
Visitor::Visit(node->statement);
|
Visitor::Visit(node->statement);
|
||||||
out_ << "</For>\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(LoopLoop* node) {
|
void PrintVisitor::Visit(LoopLoop* node) {
|
||||||
out_ << "<Loop>\n";
|
out_ << "(Loop\n";
|
||||||
Visitor::Visit(node->statement);
|
Visitor::Visit(node->statement);
|
||||||
out_ << "<\n/Loop>\n";
|
out_ << "\nLoop)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Statements, expressions, blocks, etc. -----------------
|
// Statements, expressions, blocks, etc. -----------------
|
||||||
|
|
||||||
void PrintVisitor::Visit(Block* node) {
|
void PrintVisitor::Visit(Block* node) {
|
||||||
out_ << "<Block> {\n";
|
out_ << "(Block {\n";
|
||||||
for (auto& statement : node->statements) {
|
for (auto& statement : node->statements) {
|
||||||
Visitor::Visit(statement);
|
Visitor::Visit(statement);
|
||||||
}
|
}
|
||||||
out_ << "} </Block>\n";
|
out_ << "} )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(ScopedStatement* node) {
|
void PrintVisitor::Visit(ScopedStatement* node) {
|
||||||
out_ << "<Scoped> ( ";
|
out_ << "(Scoped ( ";
|
||||||
Visitor::Visit(node->statement);
|
Visitor::Visit(node->statement);
|
||||||
out_ << " ) </Scoped>";
|
out_ << " ) )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(LoopControlExpression& node) { // enum
|
void PrintVisitor::Visit(LoopControlExpression& node) { // enum
|
||||||
switch (node) {
|
switch (node) {
|
||||||
case LoopControlExpression::Break:
|
case LoopControlExpression::Break:
|
||||||
out_ << "<Break/>\n";
|
out_ << "(Break/>\n";
|
||||||
break;
|
break;
|
||||||
case LoopControlExpression::Continue:
|
case LoopControlExpression::Continue:
|
||||||
out_ << "<Continue/>\n";
|
out_ << "(Continue/>\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -365,66 +365,66 @@ void PrintVisitor::Visit(LoopControlExpression& node) { // enum
|
||||||
// Operators
|
// Operators
|
||||||
|
|
||||||
void PrintVisitor::Visit(BinaryOperatorExpression* node) {
|
void PrintVisitor::Visit(BinaryOperatorExpression* node) {
|
||||||
out_ << "<BinaryOperator> ";
|
out_ << "(BinaryOperator ";
|
||||||
Visitor::Visit(node->left_expression);
|
Visitor::Visit(node->left_expression);
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
Visit(&node->operator_name);
|
Visit(&node->operator_name);
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
Visitor::Visit(node->right_expression);
|
Visitor::Visit(node->right_expression);
|
||||||
out_ << " </BinaryOperator>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(UnaryOperatorExpression* node) {
|
void PrintVisitor::Visit(UnaryOperatorExpression* node) {
|
||||||
out_ << "<UnaryOperator> ";
|
out_ << "(UnaryOperator ";
|
||||||
Visit(&node->operator_name);
|
Visit(&node->operator_name);
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
Visitor::Visit(node->expression);
|
Visitor::Visit(node->expression);
|
||||||
out_ << " </UnaryOperator>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple Expressions
|
// Simple Expressions
|
||||||
|
|
||||||
void PrintVisitor::Visit(FunctionCallExpression* node) {
|
void PrintVisitor::Visit(FunctionCallExpression* node) {
|
||||||
out_ << "<FunctionCall> ";
|
out_ << "(FunctionCall ";
|
||||||
Visit(node->name.get());
|
Visit(node->name.get());
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
for (auto& argument : node->arguments) {
|
for (auto& argument : node->arguments) {
|
||||||
Visitor::Visit(argument);
|
Visitor::Visit(argument);
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
}
|
}
|
||||||
out_ << "</FunctionCall>";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TupleExpression* node) {
|
void PrintVisitor::Visit(TupleExpression* node) {
|
||||||
out_ << "<TupleExpression> ";
|
out_ << "(TupleExpression ";
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
for (auto& expression : node->expressions) {
|
for (auto& expression : node->expressions) {
|
||||||
out_ << "& ";
|
out_ << "& ";
|
||||||
Visitor::Visit(expression);
|
Visitor::Visit(expression);
|
||||||
}
|
}
|
||||||
out_ << " </TupleExpression>";
|
out_ << " )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(VariantExpression* node) {
|
void PrintVisitor::Visit(VariantExpression* node) {
|
||||||
out_ << "<VariantExpression> ";
|
out_ << "(VariantExpression ";
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
for (auto& expression : node->expressions) {
|
for (auto& expression : node->expressions) {
|
||||||
out_ << "& ";
|
out_ << "& ";
|
||||||
Visitor::Visit(expression);
|
Visitor::Visit(expression);
|
||||||
}
|
}
|
||||||
out_ << " </VariantExpression>";
|
out_ << " )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(ReturnExpression* node) {
|
void PrintVisitor::Visit(ReturnExpression* node) {
|
||||||
out_ << "<Return> ";
|
out_ << "(Return ";
|
||||||
Visitor::Visit(node->expression);
|
Visitor::Visit(node->expression);
|
||||||
out_ << " </Return>";
|
out_ << " )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lambda
|
// Lambda
|
||||||
|
|
||||||
void PrintVisitor::Visit(LambdaFunction* node) {
|
void PrintVisitor::Visit(LambdaFunction* node) {
|
||||||
out_ << "<LambdaFunction> \\ ";
|
out_ << "(LambdaFunction \\ ";
|
||||||
for (auto& parameter : node->parameters) {
|
for (auto& parameter : node->parameters) {
|
||||||
Visit(parameter.get());
|
Visit(parameter.get());
|
||||||
}
|
}
|
||||||
|
|
@ -436,73 +436,73 @@ void PrintVisitor::Visit(LambdaFunction* node) {
|
||||||
}
|
}
|
||||||
out_ << " -> ";
|
out_ << " -> ";
|
||||||
Visitor::Visit(node->expression);
|
Visitor::Visit(node->expression);
|
||||||
out_ << " </LambdaFunction>";
|
out_ << " )\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
|
|
||||||
void PrintVisitor::Visit(NameSuperExpression* node) {
|
void PrintVisitor::Visit(NameSuperExpression* node) {
|
||||||
out_ << "<NameSuperExpression> ";
|
out_ << "(NameSuperExpression ";
|
||||||
for (auto& variable_namespace : node->namespaces) {
|
for (auto& variable_namespace : node->namespaces) {
|
||||||
Visitor::Visit(variable_namespace);
|
Visitor::Visit(variable_namespace);
|
||||||
out_ << '.';
|
out_ << '.';
|
||||||
}
|
}
|
||||||
for (int i = 0; i < node->expressions.size(); ++i) {
|
for (size_t i = 0; i < node->expressions.size(); ++i) {
|
||||||
Visitor::Visit(node->expressions[i]);
|
Visitor::Visit(node->expressions[i]);
|
||||||
if (i + 1 < node->expressions.size()) {
|
if (i + 1 < node->expressions.size()) {
|
||||||
out_ << '.';
|
out_ << '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_ << "</NameSupperExpression>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(NameExpression* node) {
|
void PrintVisitor::Visit(NameExpression* node) {
|
||||||
out_ << "<NameExpression> ";
|
out_ << "(NameExpression ";
|
||||||
for (auto& variable_namespace : node->namespaces) {
|
for (auto& variable_namespace : node->namespaces) {
|
||||||
Visitor::Visit(variable_namespace);
|
Visitor::Visit(variable_namespace);
|
||||||
out_ << '.';
|
out_ << '.';
|
||||||
}
|
}
|
||||||
for (int i = 0; i < node->names.size(); ++i) {
|
for (size_t i = 0; i < node->names.size(); ++i) {
|
||||||
Visit(&node->names[i]);
|
Visit(&node->names[i]);
|
||||||
if (i + 1 < node->names.size()) {
|
if (i + 1 < node->names.size()) {
|
||||||
out_ << '.';
|
out_ << '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_ << "</NameExpression>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TupleName* node) {
|
void PrintVisitor::Visit(TupleName* node) {
|
||||||
out_ << "<TupleName> ";
|
out_ << "(TupleName ";
|
||||||
for (auto& name : node->names) {
|
for (auto& name : node->names) {
|
||||||
out_ << '&';
|
out_ << '&';
|
||||||
Visit(name.get());
|
Visit(name.get());
|
||||||
}
|
}
|
||||||
out_ << "</TupleName>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(VariantName* node) {
|
void PrintVisitor::Visit(VariantName* node) {
|
||||||
out_ << "<VariantName> ";
|
out_ << "(VariantName ";
|
||||||
for (auto& name : node->names) {
|
for (auto& name : node->names) {
|
||||||
out_ << '|';
|
out_ << '|';
|
||||||
Visit(name.get());
|
Visit(name.get());
|
||||||
}
|
}
|
||||||
out_ << "</VariantName>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(AnnotatedName* node) {
|
void PrintVisitor::Visit(AnnotatedName* node) {
|
||||||
out_ << "<AnnotatedName> ";
|
out_ << "(AnnotatedName ";
|
||||||
Visit(&node->name);
|
Visit(&node->name);
|
||||||
if (node->type.has_value()) {
|
if (node->type.has_value()) {
|
||||||
out_ << " : ";
|
out_ << " : ";
|
||||||
Visit(node->type.value().get());
|
Visit(node->type.value().get());
|
||||||
}
|
}
|
||||||
out_ << " </AnnotatedName>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
|
|
||||||
void PrintVisitor::Visit(TypeConstructor* node) {
|
void PrintVisitor::Visit(TypeConstructor* node) {
|
||||||
out_ << "<TypeConstructor> ";
|
out_ << "(TypeConstructor ";
|
||||||
Visit(node->type.get());
|
Visit(node->type.get());
|
||||||
out_ << '\n';
|
out_ << '\n';
|
||||||
for (auto& parameter : node->parameters) {
|
for (auto& parameter : node->parameters) {
|
||||||
|
|
@ -511,13 +511,13 @@ void PrintVisitor::Visit(TypeConstructor* node) {
|
||||||
Visitor::Visit(parameter.second);
|
Visitor::Visit(parameter.second);
|
||||||
out_ << '\n';
|
out_ << '\n';
|
||||||
}
|
}
|
||||||
out_ << "</TypeConstructor>\n";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TupleType* node) {
|
void PrintVisitor::Visit(TupleType* node) {
|
||||||
out_ << "<TupleType> ";
|
out_ << "(TupleType ";
|
||||||
if (node->type.has_value()) {
|
if (node->type.has_value()) {
|
||||||
Visit(&node->type.value()); // optional
|
Visit(&node->type.value());
|
||||||
}
|
}
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
for (auto& entity : node->entities) {
|
for (auto& entity : node->entities) {
|
||||||
|
|
@ -528,11 +528,11 @@ void PrintVisitor::Visit(TupleType* node) {
|
||||||
}
|
}
|
||||||
Visitor::Visit(entity.second);
|
Visitor::Visit(entity.second);
|
||||||
}
|
}
|
||||||
out_ << "</TupleType>";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(VariantType* node) {
|
void PrintVisitor::Visit(VariantType* node) {
|
||||||
out_ << "<VariantType> ";
|
out_ << "(VariantType ";
|
||||||
if (node->type.has_value()) {
|
if (node->type.has_value()) {
|
||||||
Visit(&node->type.value());
|
Visit(&node->type.value());
|
||||||
}
|
}
|
||||||
|
|
@ -540,18 +540,18 @@ void PrintVisitor::Visit(VariantType* node) {
|
||||||
for (auto& constructor : node->constructors) {
|
for (auto& constructor : node->constructors) {
|
||||||
out_ << "| ";
|
out_ << "| ";
|
||||||
if (std::holds_alternative<TypeIdentifierDefinition>(constructor)) {
|
if (std::holds_alternative<TypeIdentifierDefinition>(constructor)) {
|
||||||
Visit(&std::get<TypeIdentifierDefinition>(constructor));
|
Visit(&std::get<TypeIdentifierDefinition>(constructor));
|
||||||
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
|
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
|
||||||
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
|
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
|
||||||
} else {
|
} else {
|
||||||
// error
|
// error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_ << "</VariantType>";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(AnnotatedType* node) {
|
void PrintVisitor::Visit(AnnotatedType* node) {
|
||||||
out_ << "<AnnotatedType> ";
|
out_ << "(AnnotatedType ";
|
||||||
Visit(node->type_expression.get());
|
Visit(node->type_expression.get());
|
||||||
if (node->annotations.size() > 0) {
|
if (node->annotations.size() > 0) {
|
||||||
out_ << " :";
|
out_ << " :";
|
||||||
|
|
@ -560,33 +560,33 @@ void PrintVisitor::Visit(AnnotatedType* node) {
|
||||||
out_ << " ";
|
out_ << " ";
|
||||||
Visit(annotation.get());
|
Visit(annotation.get());
|
||||||
}
|
}
|
||||||
out_ << "</AnnotatedType>";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(ParametrizedType* node) {
|
void PrintVisitor::Visit(ParametrizedType* node) {
|
||||||
out_ << "<ParametrizedType> ";
|
out_ << "(ParametrizedType ";
|
||||||
Visit(node->type_expression.get());
|
Visit(node->type_expression.get());
|
||||||
for (auto& paramater : node->parameters) {
|
for (auto& paramater : node->parameters) {
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
Visitor::Visit(paramater);
|
Visitor::Visit(paramater);
|
||||||
}
|
}
|
||||||
out_ << " </ParamtrizedType>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TypeExpression* node) {
|
void PrintVisitor::Visit(TypeExpression* node) {
|
||||||
out_ << "<TypeExpression> ";
|
out_ << "(TypeExpression ";
|
||||||
for (auto& type_namespace : node->namespaces) {
|
for (auto& type_namespace : node->namespaces) {
|
||||||
Visitor::Visit(type_namespace);
|
Visitor::Visit(type_namespace);
|
||||||
out_ << '.';
|
out_ << '.';
|
||||||
}
|
}
|
||||||
Visit(&node->type);
|
Visit(&node->type);
|
||||||
out_ << " </TypeExpression>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typeclass
|
// Typeclass
|
||||||
|
|
||||||
void PrintVisitor::Visit(AnnotatedTypeclass* node) {
|
void PrintVisitor::Visit(AnnotatedTypeclass* node) {
|
||||||
out_ << "<AnnotatedTypeclass> ";
|
out_ << "(AnnotatedTypeclass ";
|
||||||
Visit(node->typeclass_expression.get());
|
Visit(node->typeclass_expression.get());
|
||||||
if (node->annotations.size() > 0) {
|
if (node->annotations.size() > 0) {
|
||||||
out_ << " :";
|
out_ << " :";
|
||||||
|
|
@ -595,49 +595,49 @@ void PrintVisitor::Visit(AnnotatedTypeclass* node) {
|
||||||
out_ << " ";
|
out_ << " ";
|
||||||
Visit(annotation.get());
|
Visit(annotation.get());
|
||||||
}
|
}
|
||||||
out_ << "</AnnotatedTypeclass>";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(ParametrizedTypeclass* node) {
|
void PrintVisitor::Visit(ParametrizedTypeclass* node) {
|
||||||
out_ << "<ParametrizedTypeclass> ";
|
out_ << "(ParametrizedTypeclass ";
|
||||||
Visit(node->typeclass_expression.get());
|
Visit(node->typeclass_expression.get());
|
||||||
for (auto& paramater : node->parameters) {
|
for (auto& paramater : node->parameters) {
|
||||||
out_ << ' ';
|
out_ << ' ';
|
||||||
Visitor::Visit(paramater);
|
Visitor::Visit(paramater);
|
||||||
}
|
}
|
||||||
out_ << " </ParamtrizedTypeclass>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(TypeclassExpression* node) {
|
void PrintVisitor::Visit(TypeclassExpression* node) {
|
||||||
out_ << "<TypeclassExpression> ";
|
out_ << "(TypeclassExpression ";
|
||||||
for (auto& typeclass_namespace : node->namespaces) {
|
for (auto& typeclass_namespace : node->namespaces) {
|
||||||
Visitor::Visit(typeclass_namespace);
|
Visitor::Visit(typeclass_namespace);
|
||||||
out_ << '.';
|
out_ << '.';
|
||||||
}
|
}
|
||||||
Visit(&node->typeclass);
|
Visit(&node->typeclass);
|
||||||
out_ << " </TypeclassExpression>";
|
out_ << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identifiers, constants, etc. -----------------
|
// Identifiers, constants, etc. -----------------
|
||||||
|
|
||||||
void PrintVisitor::Visit(AnyIdentifier* node) { // std::string
|
void PrintVisitor::Visit(AnyIdentifier* node) { // std::string
|
||||||
out_ << "<Identifier " << *node << " />";
|
out_ << "(Identifier " << *node << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(FloatNumberLiteral* node) {
|
void PrintVisitor::Visit(FloatNumberLiteral* node) {
|
||||||
out_ << "<Identifier " << node->value << " />";
|
out_ << "(FloatNumber " << node->value << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(NumberLiteral* node) {
|
void PrintVisitor::Visit(NumberLiteral* node) {
|
||||||
out_ << "<Number " << node->value << " />";
|
out_ << "(Number " << node->value << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(StringLiteral* node) {
|
void PrintVisitor::Visit(StringLiteral* node) {
|
||||||
out_ << "<String " << node->value << " />";
|
out_ << "(String " << node->value << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintVisitor::Visit(CharLiteral* node) {
|
void PrintVisitor::Visit(CharLiteral* node) {
|
||||||
out_ << "<Char " << node->value << " />";
|
out_ << "(Char " << node->value << " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace interpreter
|
} // namespace interpreter
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ void Visitor::Visit(AnyName& node) {
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
|
|
||||||
void Visitor::Visit(AnyType& node) {
|
void Visitor::Visit(AnyType& node) { // Or ScopedAnyType
|
||||||
switch (node.index()) {
|
switch (node.index()) {
|
||||||
case 0:
|
case 0:
|
||||||
Visit(std::get<std::unique_ptr<ParametrizedType>>(node).get());
|
Visit(std::get<std::unique_ptr<ParametrizedType>>(node).get());
|
||||||
|
|
@ -301,9 +301,12 @@ void Visitor::Visit(TypeSubExpression& node) {
|
||||||
void Visitor::Visit(TypeParameter& node) {
|
void Visitor::Visit(TypeParameter& node) {
|
||||||
switch (node.index()) {
|
switch (node.index()) {
|
||||||
case 0:
|
case 0:
|
||||||
Visit(std::get<std::unique_ptr<ParametrizedType>>(node).get());
|
Visit(std::get<std::unique_ptr<TypeExpression>>(node).get());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
Visit(std::get<std::unique_ptr<ParametrizedType>>(node).get());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
Visit(*std::get<std::unique_ptr<Expression>>(node).get());
|
Visit(*std::get<std::unique_ptr<Expression>>(node).get());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
29
tests/arrays.lang
Normal file
29
tests/arrays.lang
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
decl test_arrays : Unit -> Unit
|
||||||
|
def test_arrays = {
|
||||||
|
var arr1 = [1, 2, 3]
|
||||||
|
const arr2 = [] // empty array ??
|
||||||
|
var arr3 = [] : Int.5 // TODO: decide ??
|
||||||
|
const arr4= ['a'..'z']
|
||||||
|
const n = 100;
|
||||||
|
var @arr5 = @[] : @Int.n // unique pointer (??)
|
||||||
|
|
||||||
|
var @@arr6 = @@[] : @@Int.n // shared pointer (??)
|
||||||
|
var @@arr6_pointer = @@arr6
|
||||||
|
|
||||||
|
const elem1 = arr1.1
|
||||||
|
var elem2 = arr1.1
|
||||||
|
const *ref1 = *arr1.1 // reference <-> unmanaged pointer (??)
|
||||||
|
var *ref2 = *arr1.1
|
||||||
|
; *arr1.1 = 123
|
||||||
|
|
||||||
|
; ref1 = arr1.2 // set value
|
||||||
|
; *ref1 = *ref2 // set reference
|
||||||
|
|
||||||
|
// ?? references, that can't change ??
|
||||||
|
|
||||||
|
// ?? array access, array mutable access, array get reference to elem ??
|
||||||
|
// ?? arrays as basic type ??
|
||||||
|
// ?? custom allocators ??
|
||||||
|
}
|
||||||
|
|
||||||
|
// ????????????????????
|
||||||
69
tests/classes.lang
Normal file
69
tests/classes.lang
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
// ?? value - parametric classes ??
|
||||||
|
|
||||||
|
// struct fields/etc. accessible from everywere
|
||||||
|
// class fields/etc. accessible only from namespace of class or class instance (from "methods")
|
||||||
|
|
||||||
|
// points at the beginning of constructor name - amount of needed constructor prefixes ?
|
||||||
|
|
||||||
|
// ?? how to make class compositons ??
|
||||||
|
|
||||||
|
struct Fruit =
|
||||||
|
| Apple
|
||||||
|
| Orange
|
||||||
|
| Banana
|
||||||
|
|
||||||
|
struct Optional 'A =
|
||||||
|
| Some & 'A
|
||||||
|
| None
|
||||||
|
|
||||||
|
struct (Result : #Move) 'A 'B =
|
||||||
|
| & 'A
|
||||||
|
| Error & 'B
|
||||||
|
|
||||||
|
// struct (Complex : #Value) =
|
||||||
|
// & Float(0.0)
|
||||||
|
// & Float(0.0)
|
||||||
|
//
|
||||||
|
// struct Task =
|
||||||
|
// & name("Task") : String
|
||||||
|
// & duration(0.0) : Float
|
||||||
|
|
||||||
|
class Employee =
|
||||||
|
& name : String
|
||||||
|
& role :
|
||||||
|
( | Director
|
||||||
|
& importance : Float
|
||||||
|
& share : Float
|
||||||
|
| Manager
|
||||||
|
& productivity :
|
||||||
|
( Productivity
|
||||||
|
| .Low
|
||||||
|
| .Average
|
||||||
|
| .High
|
||||||
|
& duration : Float
|
||||||
|
& sleep_on_work :
|
||||||
|
(SleepOnWork
|
||||||
|
| ..Yes
|
||||||
|
| ..No
|
||||||
|
))
|
||||||
|
& salary : Int
|
||||||
|
| Programmer
|
||||||
|
& skills : Float
|
||||||
|
& current_task : Optional Task
|
||||||
|
& salary : Int)
|
||||||
|
|
||||||
|
|
||||||
|
class Bag =
|
||||||
|
&
|
||||||
|
( | Apple
|
||||||
|
| Orange
|
||||||
|
| Banana)
|
||||||
|
& bag_type :
|
||||||
|
( | Small
|
||||||
|
| Medium
|
||||||
|
& weight_kg : Int
|
||||||
|
& weight_g : Int
|
||||||
|
& weight_g : Int
|
||||||
|
| Big)
|
||||||
|
& other_things : Array Something
|
||||||
|
|
||||||
43
tests/default_constructors.lang
Normal file
43
tests/default_constructors.lang
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
namespace Employee {
|
||||||
|
decl gen_employee : Unit -> Employee
|
||||||
|
def gen_employee = {
|
||||||
|
; a = b + c
|
||||||
|
return
|
||||||
|
$Employee
|
||||||
|
& name = "John"
|
||||||
|
& role =
|
||||||
|
($Manager
|
||||||
|
& name = "John"
|
||||||
|
& productivity =
|
||||||
|
($Productivity.High
|
||||||
|
& duration = 10.3
|
||||||
|
& sleep_on_work = ($Productivity.SleepOnWork.No))
|
||||||
|
& salary = 123)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
class Employee =
|
||||||
|
& name : String
|
||||||
|
& role :
|
||||||
|
( | Director
|
||||||
|
& importance : Float
|
||||||
|
& share : Float
|
||||||
|
| Manager
|
||||||
|
& productivity :
|
||||||
|
( Productivity
|
||||||
|
| .Low
|
||||||
|
| .Average
|
||||||
|
| .High
|
||||||
|
& duration : Float
|
||||||
|
& sleep_on_work :
|
||||||
|
(SleepOnWork
|
||||||
|
| ..Yes
|
||||||
|
| ..No
|
||||||
|
))
|
||||||
|
& salary : Int
|
||||||
|
| Programmer
|
||||||
|
& skills : Float
|
||||||
|
& current_task : Optional Task
|
||||||
|
& salary : Int)
|
||||||
|
*/
|
||||||
44
tests/flow_control.lang
Normal file
44
tests/flow_control.lang
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
decl flow_control_test : Unit -> Unit
|
||||||
|
def flow_control_test = {
|
||||||
|
// if && || a < b
|
||||||
|
// || a == b
|
||||||
|
// && b < c
|
||||||
|
// && c > 10
|
||||||
|
|
||||||
|
if ((a < b) || (a == b)) && (b < c)
|
||||||
|
then IO.print x
|
||||||
|
elif x < 0
|
||||||
|
then {
|
||||||
|
; ++x
|
||||||
|
; IO.print y
|
||||||
|
} else {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (a > 0) && (!array.is_empty)
|
||||||
|
do {
|
||||||
|
; --a
|
||||||
|
; array.pop
|
||||||
|
}
|
||||||
|
|
||||||
|
while x < 10 do
|
||||||
|
x += x + 3
|
||||||
|
|
||||||
|
for i in 0..y do {
|
||||||
|
; IO.print i
|
||||||
|
}
|
||||||
|
|
||||||
|
for & i & j
|
||||||
|
in (& 0..y & 0..k)
|
||||||
|
do { // TODO: decide ??? does it work (like auto zip) ???
|
||||||
|
; IO.print 1
|
||||||
|
; IO.print 2
|
||||||
|
; IO.print 128
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
; ++y
|
||||||
|
if y > 100 then
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
70
tests/functions.lang
Normal file
70
tests/functions.lang
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
// "decl" is not required, but useful in module interface
|
||||||
|
|
||||||
|
decl sum ('A : #Add) : 'A -> 'A -> 'A
|
||||||
|
def sum : a b = a + b
|
||||||
|
|
||||||
|
decl fib : Int -> Int
|
||||||
|
def fib : n =
|
||||||
|
match n with
|
||||||
|
| 0 | 1 -> 1
|
||||||
|
| _ -> fib (n - 1) + fib n
|
||||||
|
|
||||||
|
decl fact : Int -> Int
|
||||||
|
def fact : n =
|
||||||
|
match n with
|
||||||
|
| 0 -> 1
|
||||||
|
| n -> n * fact (n - 1)
|
||||||
|
|
||||||
|
decl find_prefix_hashes ('H : (#AccHash Char)) : String -> Array 'H
|
||||||
|
def find_prefix_hashes ('H : (#AccHash Char)) : str = {
|
||||||
|
var hashes = (Array 'H).new (str.size + 1)
|
||||||
|
|
||||||
|
; hashes.0 = 'H.of str.0
|
||||||
|
for i in 1..hashes.size do {
|
||||||
|
; hashes.i = hashes.(i - 1).clone
|
||||||
|
; hashes.i.append str.i
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashes
|
||||||
|
}
|
||||||
|
|
||||||
|
// ?? other default constructor symbol (instead of placeholder _), etc. ??
|
||||||
|
|
||||||
|
// seporate first and last iteration of loop ?
|
||||||
|
// previous and next iterations ?
|
||||||
|
|
||||||
|
decl find_substring : String -> String -> Array Index
|
||||||
|
def find_substring : str substr = {
|
||||||
|
alias Hash = AccHash Char
|
||||||
|
|
||||||
|
var result = (Array Index).empty
|
||||||
|
|
||||||
|
const str_hashes = find_prefix_hashes Hash str
|
||||||
|
const substr_hash = Hash.of substr
|
||||||
|
|
||||||
|
for i in 0..(str_hashes.size - substr.size) do {
|
||||||
|
const part_hash = Hash.diff str_hashes.(i + substr.size) str_hashes.i
|
||||||
|
|
||||||
|
if part_hash == substr_hash then {
|
||||||
|
; result.push i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
decl is_empty : Unit -> Bool
|
||||||
|
def is_empty =
|
||||||
|
return 0
|
||||||
|
|
||||||
|
decl do_something : Unit -> Unit
|
||||||
|
def do_something =
|
||||||
|
IO.print "Hello World!"
|
||||||
|
|
||||||
|
decl mul : Int -> Int -> Int
|
||||||
|
def mul : x y = x * y
|
||||||
|
|
||||||
|
decl mul_10 : Int -> Int
|
||||||
|
def mul_10 = mul 10 // or argument can be used
|
||||||
|
|
||||||
|
// ?? is partial application feature needed ??
|
||||||
18
tests/import.lang
Normal file
18
tests/import.lang
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import "module"
|
||||||
|
import "module" : func
|
||||||
|
import "module" :
|
||||||
|
func1
|
||||||
|
func2
|
||||||
|
func3
|
||||||
|
func4
|
||||||
|
func5
|
||||||
|
|
||||||
|
use ModuleNamespace = import "module"
|
||||||
|
|
||||||
|
use PartOfModuleNamespace =
|
||||||
|
import "module" :
|
||||||
|
func1
|
||||||
|
func2
|
||||||
|
func3
|
||||||
|
|
||||||
|
// ?? use ":" once again ??
|
||||||
15
tests/lambdas.lang
Normal file
15
tests/lambdas.lang
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
decl test_lambdas : Unit -> Unit
|
||||||
|
def test_lambdas = {
|
||||||
|
const lambda1 = \x -> x * x
|
||||||
|
// const lambda2 = \(x : #Hash) -> x.hash // ??
|
||||||
|
const lambda3 = \x y -> x + y
|
||||||
|
|
||||||
|
// TODO: type LambdaType = Int -> Int // ?? type keyword ??
|
||||||
|
// const typed_lambda = \x -> x + 1
|
||||||
|
|
||||||
|
const lambda4 = \x -> {
|
||||||
|
; IO.print x
|
||||||
|
const y = x + x
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
}
|
||||||
15
tests/match.lang
Normal file
15
tests/match.lang
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
def fruit_cost : fruit = {
|
||||||
|
return (match fruit with
|
||||||
|
| $Banana -> 11
|
||||||
|
| $Apple | $Orange -> 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
def amount_to_string : x is_zero_separated = {
|
||||||
|
const ans = match x with
|
||||||
|
| 0 ? is_zero_separated -> "Zero"
|
||||||
|
| 0 | 1 | 2 | 3 | 4 -> "Few"
|
||||||
|
| x ? (5..9).contains x -> "Several"
|
||||||
|
| x ? (10..19).contains x -> "Pack"
|
||||||
|
| _ -> "Lots"
|
||||||
|
return ans
|
||||||
|
}
|
||||||
9
tests/memory.lang
Normal file
9
tests/memory.lang
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
struct StructWithRef =
|
||||||
|
& @Int._ // unique pointer to any-sized array (default size is zero ??)
|
||||||
|
|
||||||
|
decl test_memory : Unit -> Unit
|
||||||
|
def test_memory = {
|
||||||
|
const @unique_ref1 <- @5 // move unique reference
|
||||||
|
var @unique_ref2 <- @(Array.of 1 2 3)
|
||||||
|
// ?? reference to constant value ??
|
||||||
|
}
|
||||||
20
tests/namespaces.lang
Normal file
20
tests/namespaces.lang
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace Namespace {
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Array 'A {
|
||||||
|
decl something : Unit
|
||||||
|
// "static methods" of Array 'a class
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Array ('A : #Copy) {
|
||||||
|
decl something : Unit
|
||||||
|
// "static methods" of Array 'a with "copyable" 'a
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace var a : Array ('A : #Copy) {
|
||||||
|
decl something : Unit
|
||||||
|
// "methods" of Array 'a (a as array instance) with "copyable" 'a
|
||||||
|
}
|
||||||
|
|
||||||
|
// ?? what to do with const/public/... methods ??
|
||||||
5
tests/parametric_types.lang
Normal file
5
tests/parametric_types.lang
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
class (FixedArray : #Ord) 'A : (a : Int) =
|
||||||
|
& size(a) : Int // ?? const ??
|
||||||
|
& @[] : @'A.a
|
||||||
|
|
||||||
|
// ?? not shure about array definition ??
|
||||||
38
tests/partitions.lang
Normal file
38
tests/partitions.lang
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
// partition DOC { // or .doc.lang filename
|
||||||
|
// // ...
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ?? separated doc ??
|
||||||
|
|
||||||
|
partition TEST { // or .test.lang filename
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
partition INTERFACE { // or .interface.lang filename
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
partition CORE { // or .core.lang filename
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
partition LIB { // or .lib.lang filename
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
partition MODULE { // or .module.lang filename
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// maybe another name for partition
|
||||||
|
|
||||||
|
partition EXE { // or .exe.lang filename
|
||||||
|
decl something : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// partition CONFIG { // or .config.lang filename
|
||||||
|
// decl something : Unit
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ?? config is one of the partitions ??
|
||||||
|
// ?? maybe more ??
|
||||||
12
tests/tuples.lang
Normal file
12
tests/tuples.lang
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
decl test_tuples : Unit -> Unit
|
||||||
|
def test_tuples = {
|
||||||
|
var tuple1 = & "a" & 2 & "hello"
|
||||||
|
const & t1 & t2 & t3 = f x
|
||||||
|
|
||||||
|
; tuple1.0 = "b"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ??????????????????????????
|
||||||
|
|
||||||
|
|
||||||
7
tests/type_casting.lang
Normal file
7
tests/type_casting.lang
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
decl test_type_casting : Unit -> Unit
|
||||||
|
def test_type_casting = {
|
||||||
|
var x = y.as Int
|
||||||
|
var k = (f y x).as Float
|
||||||
|
}
|
||||||
|
|
||||||
|
// type casting is can be done by generic method "as"
|
||||||
36
tests/typeclasses.lang
Normal file
36
tests/typeclasses.lang
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
typeclass #Copy =
|
||||||
|
& copy : #Copy -> #Copy
|
||||||
|
|
||||||
|
typeclass (#Ord : #Eq) =
|
||||||
|
& ( < ) : #Ord -> #Ord -> Bool
|
||||||
|
& ( > ) : #Ord -> #Ord -> Bool
|
||||||
|
& ( <= ) : #Ord -> #Ord -> Bool
|
||||||
|
& ( >= ) : #Ord -> #Ord -> Bool
|
||||||
|
|
||||||
|
typeclass (#D : #A #B #C) 'A 'B =
|
||||||
|
& do_something : Unit -> (& 'A & 'B)
|
||||||
|
|
||||||
|
typeclass #E 'A =
|
||||||
|
& do_something : Unit -> 'A
|
||||||
|
|
||||||
|
namespace const ord : #Ord {
|
||||||
|
def ( <= ) : a b = (a < b) || (a == b)
|
||||||
|
def ( > ) : a b = !(a <= b)
|
||||||
|
def ( >= ) : a b = !(a < b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// === ?? dependent types ?? ===
|
||||||
|
//
|
||||||
|
// typeclass #F : (a : Int) (b : Int) =
|
||||||
|
// & do_something Int -> Int
|
||||||
|
//
|
||||||
|
// namespace (f : #F a b c) {
|
||||||
|
// require do_sometihng a = b
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ===
|
||||||
|
|
||||||
|
// ?? operators over functions (without arguments, like "def <= = < || ==;") ??
|
||||||
|
// ?? define operators like OCaml ??
|
||||||
|
// ?? denote moved type ??
|
||||||
|
// ?? "trait" VS "typeclass" ??
|
||||||
14
tests/types.lang
Normal file
14
tests/types.lang
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
alias T1 = Int;
|
||||||
|
|
||||||
|
type (T2 : #A #B #C);
|
||||||
|
|
||||||
|
// Define file level abstract type
|
||||||
|
|
||||||
|
T2 =
|
||||||
|
| Int
|
||||||
|
| Float
|
||||||
|
| Complex;
|
||||||
|
|
||||||
|
// Compile module (functions, types, ...) for T2 = Int, Float, Complex
|
||||||
|
|
||||||
|
// ?? file level <-> module level ??
|
||||||
22
tests/variants.lang
Normal file
22
tests/variants.lang
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
decl test_variants : Unit -> Unit
|
||||||
|
def test_variants = {
|
||||||
|
var variant1 = | 'a' | 2 | "hello"
|
||||||
|
var | val | err = f x // optional types for each
|
||||||
|
|
||||||
|
; val -> "something" // open variant as value in expr
|
||||||
|
|
||||||
|
; val -!> "nothing" // open variant as None in expr
|
||||||
|
|
||||||
|
; ?err // open variant as value, or return None (if possible), operator
|
||||||
|
|
||||||
|
match variant1 with
|
||||||
|
| 'a' -> "something"
|
||||||
|
| 2 -> "something"
|
||||||
|
| "hello" -> "something"
|
||||||
|
| a -> "Something"
|
||||||
|
| String.of str -> "something"
|
||||||
|
| Int.of i -> "someting"
|
||||||
|
| 11 -> "nothing"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ???????????????????????
|
||||||
1
tree-sitter
Submodule
1
tree-sitter
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 1b1c3974f789a9bfaa31f493e6eaa212f13bdfb9
|
||||||
|
|
@ -1,983 +0,0 @@
|
||||||
#ifndef TREE_SITTER_API_H_
|
|
||||||
#define TREE_SITTER_API_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/****************************/
|
|
||||||
/* Section - ABI Versioning */
|
|
||||||
/****************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The latest ABI version that is supported by the current version of the
|
|
||||||
* library. When Languages are generated by the Tree-sitter CLI, they are
|
|
||||||
* assigned an ABI version number that corresponds to the current CLI version.
|
|
||||||
* The Tree-sitter library is generally backwards-compatible with languages
|
|
||||||
* generated using older CLI versions, but is not forwards-compatible.
|
|
||||||
*/
|
|
||||||
#define TREE_SITTER_LANGUAGE_VERSION 14
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The earliest ABI version that is supported by the current version of the
|
|
||||||
* library.
|
|
||||||
*/
|
|
||||||
#define TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION 13
|
|
||||||
|
|
||||||
/*******************/
|
|
||||||
/* Section - Types */
|
|
||||||
/*******************/
|
|
||||||
|
|
||||||
typedef uint16_t TSSymbol;
|
|
||||||
typedef uint16_t TSFieldId;
|
|
||||||
typedef struct TSLanguage TSLanguage;
|
|
||||||
typedef struct TSParser TSParser;
|
|
||||||
typedef struct TSTree TSTree;
|
|
||||||
typedef struct TSQuery TSQuery;
|
|
||||||
typedef struct TSQueryCursor TSQueryCursor;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSInputEncodingUTF8,
|
|
||||||
TSInputEncodingUTF16,
|
|
||||||
} TSInputEncoding;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSSymbolTypeRegular,
|
|
||||||
TSSymbolTypeAnonymous,
|
|
||||||
TSSymbolTypeAuxiliary,
|
|
||||||
} TSSymbolType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t row;
|
|
||||||
uint32_t column;
|
|
||||||
} TSPoint;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TSPoint start_point;
|
|
||||||
TSPoint end_point;
|
|
||||||
uint32_t start_byte;
|
|
||||||
uint32_t end_byte;
|
|
||||||
} TSRange;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void *payload;
|
|
||||||
const char *(*read)(void *payload, uint32_t byte_index, TSPoint position, uint32_t *bytes_read);
|
|
||||||
TSInputEncoding encoding;
|
|
||||||
} TSInput;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSLogTypeParse,
|
|
||||||
TSLogTypeLex,
|
|
||||||
} TSLogType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void *payload;
|
|
||||||
void (*log)(void *payload, TSLogType, const char *);
|
|
||||||
} TSLogger;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t start_byte;
|
|
||||||
uint32_t old_end_byte;
|
|
||||||
uint32_t new_end_byte;
|
|
||||||
TSPoint start_point;
|
|
||||||
TSPoint old_end_point;
|
|
||||||
TSPoint new_end_point;
|
|
||||||
} TSInputEdit;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t context[4];
|
|
||||||
const void *id;
|
|
||||||
const TSTree *tree;
|
|
||||||
} TSNode;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const void *tree;
|
|
||||||
const void *id;
|
|
||||||
uint32_t context[2];
|
|
||||||
} TSTreeCursor;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TSNode node;
|
|
||||||
uint32_t index;
|
|
||||||
} TSQueryCapture;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSQuantifierZero = 0, // must match the array initialization value
|
|
||||||
TSQuantifierZeroOrOne,
|
|
||||||
TSQuantifierZeroOrMore,
|
|
||||||
TSQuantifierOne,
|
|
||||||
TSQuantifierOneOrMore,
|
|
||||||
} TSQuantifier;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t id;
|
|
||||||
uint16_t pattern_index;
|
|
||||||
uint16_t capture_count;
|
|
||||||
const TSQueryCapture *captures;
|
|
||||||
} TSQueryMatch;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSQueryPredicateStepTypeDone,
|
|
||||||
TSQueryPredicateStepTypeCapture,
|
|
||||||
TSQueryPredicateStepTypeString,
|
|
||||||
} TSQueryPredicateStepType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TSQueryPredicateStepType type;
|
|
||||||
uint32_t value_id;
|
|
||||||
} TSQueryPredicateStep;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSQueryErrorNone = 0,
|
|
||||||
TSQueryErrorSyntax,
|
|
||||||
TSQueryErrorNodeType,
|
|
||||||
TSQueryErrorField,
|
|
||||||
TSQueryErrorCapture,
|
|
||||||
TSQueryErrorStructure,
|
|
||||||
TSQueryErrorLanguage,
|
|
||||||
} TSQueryError;
|
|
||||||
|
|
||||||
/********************/
|
|
||||||
/* Section - Parser */
|
|
||||||
/********************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new parser.
|
|
||||||
*/
|
|
||||||
TSParser *ts_parser_new(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the parser, freeing all of the memory that it used.
|
|
||||||
*/
|
|
||||||
void ts_parser_delete(TSParser *parser);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the language that the parser should use for parsing.
|
|
||||||
*
|
|
||||||
* Returns a boolean indicating whether or not the language was successfully
|
|
||||||
* assigned. True means assignment succeeded. False means there was a version
|
|
||||||
* mismatch: the language was generated with an incompatible version of the
|
|
||||||
* Tree-sitter CLI. Check the language's version using `ts_language_version`
|
|
||||||
* and compare it to this library's `TREE_SITTER_LANGUAGE_VERSION` and
|
|
||||||
* `TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION` constants.
|
|
||||||
*/
|
|
||||||
bool ts_parser_set_language(TSParser *self, const TSLanguage *language);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the parser's current language.
|
|
||||||
*/
|
|
||||||
const TSLanguage *ts_parser_language(const TSParser *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the ranges of text that the parser should include when parsing.
|
|
||||||
*
|
|
||||||
* By default, the parser will always include entire documents. This function
|
|
||||||
* allows you to parse only a *portion* of a document but still return a syntax
|
|
||||||
* tree whose ranges match up with the document as a whole. You can also pass
|
|
||||||
* multiple disjoint ranges.
|
|
||||||
*
|
|
||||||
* The second and third parameters specify the location and length of an array
|
|
||||||
* of ranges. The parser does *not* take ownership of these ranges; it copies
|
|
||||||
* the data, so it doesn't matter how these ranges are allocated.
|
|
||||||
*
|
|
||||||
* If `length` is zero, then the entire document will be parsed. Otherwise,
|
|
||||||
* the given ranges must be ordered from earliest to latest in the document,
|
|
||||||
* and they must not overlap. That is, the following must hold for all
|
|
||||||
* `i` < `length - 1`: ranges[i].end_byte <= ranges[i + 1].start_byte
|
|
||||||
*
|
|
||||||
* If this requirement is not satisfied, the operation will fail, the ranges
|
|
||||||
* will not be assigned, and this function will return `false`. On success,
|
|
||||||
* this function returns `true`
|
|
||||||
*/
|
|
||||||
bool ts_parser_set_included_ranges(
|
|
||||||
TSParser *self,
|
|
||||||
const TSRange *ranges,
|
|
||||||
uint32_t length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the ranges of text that the parser will include when parsing.
|
|
||||||
*
|
|
||||||
* The returned pointer is owned by the parser. The caller should not free it
|
|
||||||
* or write to it. The length of the array will be written to the given
|
|
||||||
* `length` pointer.
|
|
||||||
*/
|
|
||||||
const TSRange *ts_parser_included_ranges(
|
|
||||||
const TSParser *self,
|
|
||||||
uint32_t *length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the parser to parse some source code and create a syntax tree.
|
|
||||||
*
|
|
||||||
* If you are parsing this document for the first time, pass `NULL` for the
|
|
||||||
* `old_tree` parameter. Otherwise, if you have already parsed an earlier
|
|
||||||
* version of this document and the document has since been edited, pass the
|
|
||||||
* previous syntax tree so that the unchanged parts of it can be reused.
|
|
||||||
* This will save time and memory. For this to work correctly, you must have
|
|
||||||
* already edited the old syntax tree using the `ts_tree_edit` function in a
|
|
||||||
* way that exactly matches the source code changes.
|
|
||||||
*
|
|
||||||
* The `TSInput` parameter lets you specify how to read the text. It has the
|
|
||||||
* following three fields:
|
|
||||||
* 1. `read`: A function to retrieve a chunk of text at a given byte offset
|
|
||||||
* and (row, column) position. The function should return a pointer to the
|
|
||||||
* text and write its length to the `bytes_read` pointer. The parser does
|
|
||||||
* not take ownership of this buffer; it just borrows it until it has
|
|
||||||
* finished reading it. The function should write a zero value to the
|
|
||||||
* `bytes_read` pointer to indicate the end of the document.
|
|
||||||
* 2. `payload`: An arbitrary pointer that will be passed to each invocation
|
|
||||||
* of the `read` function.
|
|
||||||
* 3. `encoding`: An indication of how the text is encoded. Either
|
|
||||||
* `TSInputEncodingUTF8` or `TSInputEncodingUTF16`.
|
|
||||||
*
|
|
||||||
* This function returns a syntax tree on success, and `NULL` on failure. There
|
|
||||||
* are three possible reasons for failure:
|
|
||||||
* 1. The parser does not have a language assigned. Check for this using the
|
|
||||||
`ts_parser_language` function.
|
|
||||||
* 2. Parsing was cancelled due to a timeout that was set by an earlier call to
|
|
||||||
* the `ts_parser_set_timeout_micros` function. You can resume parsing from
|
|
||||||
* where the parser left out by calling `ts_parser_parse` again with the
|
|
||||||
* same arguments. Or you can start parsing from scratch by first calling
|
|
||||||
* `ts_parser_reset`.
|
|
||||||
* 3. Parsing was cancelled using a cancellation flag that was set by an
|
|
||||||
* earlier call to `ts_parser_set_cancellation_flag`. You can resume parsing
|
|
||||||
* from where the parser left out by calling `ts_parser_parse` again with
|
|
||||||
* the same arguments.
|
|
||||||
*/
|
|
||||||
TSTree *ts_parser_parse(
|
|
||||||
TSParser *self,
|
|
||||||
const TSTree *old_tree,
|
|
||||||
TSInput input
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the parser to parse some source code stored in one contiguous buffer.
|
|
||||||
* The first two parameters are the same as in the `ts_parser_parse` function
|
|
||||||
* above. The second two parameters indicate the location of the buffer and its
|
|
||||||
* length in bytes.
|
|
||||||
*/
|
|
||||||
TSTree *ts_parser_parse_string(
|
|
||||||
TSParser *self,
|
|
||||||
const TSTree *old_tree,
|
|
||||||
const char *string,
|
|
||||||
uint32_t length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the parser to parse some source code stored in one contiguous buffer with
|
|
||||||
* a given encoding. The first four parameters work the same as in the
|
|
||||||
* `ts_parser_parse_string` method above. The final parameter indicates whether
|
|
||||||
* the text is encoded as UTF8 or UTF16.
|
|
||||||
*/
|
|
||||||
TSTree *ts_parser_parse_string_encoding(
|
|
||||||
TSParser *self,
|
|
||||||
const TSTree *old_tree,
|
|
||||||
const char *string,
|
|
||||||
uint32_t length,
|
|
||||||
TSInputEncoding encoding
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instruct the parser to start the next parse from the beginning.
|
|
||||||
*
|
|
||||||
* If the parser previously failed because of a timeout or a cancellation, then
|
|
||||||
* by default, it will resume where it left off on the next call to
|
|
||||||
* `ts_parser_parse` or other parsing functions. If you don't want to resume,
|
|
||||||
* and instead intend to use this parser to parse some other document, you must
|
|
||||||
* call `ts_parser_reset` first.
|
|
||||||
*/
|
|
||||||
void ts_parser_reset(TSParser *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the maximum duration in microseconds that parsing should be allowed to
|
|
||||||
* take before halting.
|
|
||||||
*
|
|
||||||
* If parsing takes longer than this, it will halt early, returning NULL.
|
|
||||||
* See `ts_parser_parse` for more information.
|
|
||||||
*/
|
|
||||||
void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the duration in microseconds that parsing is allowed to take.
|
|
||||||
*/
|
|
||||||
uint64_t ts_parser_timeout_micros(const TSParser *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the parser's current cancellation flag pointer.
|
|
||||||
*
|
|
||||||
* If a non-null pointer is assigned, then the parser will periodically read
|
|
||||||
* from this pointer during parsing. If it reads a non-zero value, it will
|
|
||||||
* halt early, returning NULL. See `ts_parser_parse` for more information.
|
|
||||||
*/
|
|
||||||
void ts_parser_set_cancellation_flag(TSParser *self, const size_t *flag);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the parser's current cancellation flag pointer.
|
|
||||||
*/
|
|
||||||
const size_t *ts_parser_cancellation_flag(const TSParser *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the logger that a parser should use during parsing.
|
|
||||||
*
|
|
||||||
* The parser does not take ownership over the logger payload. If a logger was
|
|
||||||
* previously assigned, the caller is responsible for releasing any memory
|
|
||||||
* owned by the previous logger.
|
|
||||||
*/
|
|
||||||
void ts_parser_set_logger(TSParser *self, TSLogger logger);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the parser's current logger.
|
|
||||||
*/
|
|
||||||
TSLogger ts_parser_logger(const TSParser *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file descriptor to which the parser should write debugging graphs
|
|
||||||
* during parsing. The graphs are formatted in the DOT language. You may want
|
|
||||||
* to pipe these graphs directly to a `dot(1)` process in order to generate
|
|
||||||
* SVG output. You can turn off this logging by passing a negative number.
|
|
||||||
*/
|
|
||||||
void ts_parser_print_dot_graphs(TSParser *self, int file);
|
|
||||||
|
|
||||||
/******************/
|
|
||||||
/* Section - Tree */
|
|
||||||
/******************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a shallow copy of the syntax tree. This is very fast.
|
|
||||||
*
|
|
||||||
* You need to copy a syntax tree in order to use it on more than one thread at
|
|
||||||
* a time, as syntax trees are not thread safe.
|
|
||||||
*/
|
|
||||||
TSTree *ts_tree_copy(const TSTree *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the syntax tree, freeing all of the memory that it used.
|
|
||||||
*/
|
|
||||||
void ts_tree_delete(TSTree *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the root node of the syntax tree.
|
|
||||||
*/
|
|
||||||
TSNode ts_tree_root_node(const TSTree *self);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the root node of the syntax tree, but with its position
|
|
||||||
* shifted forward by the given offset.
|
|
||||||
*/
|
|
||||||
TSNode ts_tree_root_node_with_offset(
|
|
||||||
const TSTree *self,
|
|
||||||
uint32_t offset_bytes,
|
|
||||||
TSPoint offset_point
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the language that was used to parse the syntax tree.
|
|
||||||
*/
|
|
||||||
const TSLanguage *ts_tree_language(const TSTree *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the array of included ranges that was used to parse the syntax tree.
|
|
||||||
*
|
|
||||||
* The returned pointer must be freed by the caller.
|
|
||||||
*/
|
|
||||||
TSRange *ts_tree_included_ranges(const TSTree *, uint32_t *length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit the syntax tree to keep it in sync with source code that has been
|
|
||||||
* edited.
|
|
||||||
*
|
|
||||||
* You must describe the edit both in terms of byte offsets and in terms of
|
|
||||||
* (row, column) coordinates.
|
|
||||||
*/
|
|
||||||
void ts_tree_edit(TSTree *self, const TSInputEdit *edit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare an old edited syntax tree to a new syntax tree representing the same
|
|
||||||
* document, returning an array of ranges whose syntactic structure has changed.
|
|
||||||
*
|
|
||||||
* For this to work correctly, the old syntax tree must have been edited such
|
|
||||||
* that its ranges match up to the new tree. Generally, you'll want to call
|
|
||||||
* this function right after calling one of the `ts_parser_parse` functions.
|
|
||||||
* You need to pass the old tree that was passed to parse, as well as the new
|
|
||||||
* tree that was returned from that function.
|
|
||||||
*
|
|
||||||
* The returned array is allocated using `malloc` and the caller is responsible
|
|
||||||
* for freeing it using `free`. The length of the array will be written to the
|
|
||||||
* given `length` pointer.
|
|
||||||
*/
|
|
||||||
TSRange *ts_tree_get_changed_ranges(
|
|
||||||
const TSTree *old_tree,
|
|
||||||
const TSTree *new_tree,
|
|
||||||
uint32_t *length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a DOT graph describing the syntax tree to the given file.
|
|
||||||
*/
|
|
||||||
void ts_tree_print_dot_graph(const TSTree *, int file_descriptor);
|
|
||||||
|
|
||||||
/******************/
|
|
||||||
/* Section - Node */
|
|
||||||
/******************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's type as a null-terminated string.
|
|
||||||
*/
|
|
||||||
const char *ts_node_type(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's type as a numerical id.
|
|
||||||
*/
|
|
||||||
TSSymbol ts_node_symbol(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's start byte.
|
|
||||||
*/
|
|
||||||
uint32_t ts_node_start_byte(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's start position in terms of rows and columns.
|
|
||||||
*/
|
|
||||||
TSPoint ts_node_start_point(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's end byte.
|
|
||||||
*/
|
|
||||||
uint32_t ts_node_end_byte(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's end position in terms of rows and columns.
|
|
||||||
*/
|
|
||||||
TSPoint ts_node_end_point(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an S-expression representing the node as a string.
|
|
||||||
*
|
|
||||||
* This string is allocated with `malloc` and the caller is responsible for
|
|
||||||
* freeing it using `free`.
|
|
||||||
*/
|
|
||||||
char *ts_node_string(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the node is null. Functions like `ts_node_child` and
|
|
||||||
* `ts_node_next_sibling` will return a null node to indicate that no such node
|
|
||||||
* was found.
|
|
||||||
*/
|
|
||||||
bool ts_node_is_null(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the node is *named*. Named nodes correspond to named rules in the
|
|
||||||
* grammar, whereas *anonymous* nodes correspond to string literals in the
|
|
||||||
* grammar.
|
|
||||||
*/
|
|
||||||
bool ts_node_is_named(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the node is *missing*. Missing nodes are inserted by the parser in
|
|
||||||
* order to recover from certain kinds of syntax errors.
|
|
||||||
*/
|
|
||||||
bool ts_node_is_missing(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the node is *extra*. Extra nodes represent things like comments,
|
|
||||||
* which are not required the grammar, but can appear anywhere.
|
|
||||||
*/
|
|
||||||
bool ts_node_is_extra(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a syntax node has been edited.
|
|
||||||
*/
|
|
||||||
bool ts_node_has_changes(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the node is a syntax error or contains any syntax errors.
|
|
||||||
*/
|
|
||||||
bool ts_node_has_error(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's immediate parent.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_parent(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's child at the given index, where zero represents the first
|
|
||||||
* child.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_child(TSNode, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the field name for node's child at the given index, where zero represents
|
|
||||||
* the first child. Returns NULL, if no field is found.
|
|
||||||
*/
|
|
||||||
const char *ts_node_field_name_for_child(TSNode, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's number of children.
|
|
||||||
*/
|
|
||||||
uint32_t ts_node_child_count(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's *named* child at the given index.
|
|
||||||
*
|
|
||||||
* See also `ts_node_is_named`.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_named_child(TSNode, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's number of *named* children.
|
|
||||||
*
|
|
||||||
* See also `ts_node_is_named`.
|
|
||||||
*/
|
|
||||||
uint32_t ts_node_named_child_count(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's child with the given field name.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_child_by_field_name(
|
|
||||||
TSNode self,
|
|
||||||
const char *field_name,
|
|
||||||
uint32_t field_name_length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's child with the given numerical field id.
|
|
||||||
*
|
|
||||||
* You can convert a field name to an id using the
|
|
||||||
* `ts_language_field_id_for_name` function.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_child_by_field_id(TSNode, TSFieldId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's next / previous sibling.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_next_sibling(TSNode);
|
|
||||||
TSNode ts_node_prev_sibling(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's next / previous *named* sibling.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_next_named_sibling(TSNode);
|
|
||||||
TSNode ts_node_prev_named_sibling(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's first child that extends beyond the given byte offset.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_first_child_for_byte(TSNode, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the node's first named child that extends beyond the given byte offset.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_first_named_child_for_byte(TSNode, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the smallest node within this node that spans the given range of bytes
|
|
||||||
* or (row, column) positions.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_descendant_for_byte_range(TSNode, uint32_t, uint32_t);
|
|
||||||
TSNode ts_node_descendant_for_point_range(TSNode, TSPoint, TSPoint);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the smallest named node within this node that spans the given range of
|
|
||||||
* bytes or (row, column) positions.
|
|
||||||
*/
|
|
||||||
TSNode ts_node_named_descendant_for_byte_range(TSNode, uint32_t, uint32_t);
|
|
||||||
TSNode ts_node_named_descendant_for_point_range(TSNode, TSPoint, TSPoint);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit the node to keep it in-sync with source code that has been edited.
|
|
||||||
*
|
|
||||||
* This function is only rarely needed. When you edit a syntax tree with the
|
|
||||||
* `ts_tree_edit` function, all of the nodes that you retrieve from the tree
|
|
||||||
* afterward will already reflect the edit. You only need to use `ts_node_edit`
|
|
||||||
* when you have a `TSNode` instance that you want to keep and continue to use
|
|
||||||
* after an edit.
|
|
||||||
*/
|
|
||||||
void ts_node_edit(TSNode *, const TSInputEdit *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if two nodes are identical.
|
|
||||||
*/
|
|
||||||
bool ts_node_eq(TSNode, TSNode);
|
|
||||||
|
|
||||||
/************************/
|
|
||||||
/* Section - TreeCursor */
|
|
||||||
/************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new tree cursor starting from the given node.
|
|
||||||
*
|
|
||||||
* A tree cursor allows you to walk a syntax tree more efficiently than is
|
|
||||||
* possible using the `TSNode` functions. It is a mutable object that is always
|
|
||||||
* on a certain syntax node, and can be moved imperatively to different nodes.
|
|
||||||
*/
|
|
||||||
TSTreeCursor ts_tree_cursor_new(TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a tree cursor, freeing all of the memory that it used.
|
|
||||||
*/
|
|
||||||
void ts_tree_cursor_delete(TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-initialize a tree cursor to start at a different node.
|
|
||||||
*/
|
|
||||||
void ts_tree_cursor_reset(TSTreeCursor *, TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the tree cursor's current node.
|
|
||||||
*/
|
|
||||||
TSNode ts_tree_cursor_current_node(const TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the field name of the tree cursor's current node.
|
|
||||||
*
|
|
||||||
* This returns `NULL` if the current node doesn't have a field.
|
|
||||||
* See also `ts_node_child_by_field_name`.
|
|
||||||
*/
|
|
||||||
const char *ts_tree_cursor_current_field_name(const TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the field id of the tree cursor's current node.
|
|
||||||
*
|
|
||||||
* This returns zero if the current node doesn't have a field.
|
|
||||||
* See also `ts_node_child_by_field_id`, `ts_language_field_id_for_name`.
|
|
||||||
*/
|
|
||||||
TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the cursor to the parent of its current node.
|
|
||||||
*
|
|
||||||
* This returns `true` if the cursor successfully moved, and returns `false`
|
|
||||||
* if there was no parent node (the cursor was already on the root node).
|
|
||||||
*/
|
|
||||||
bool ts_tree_cursor_goto_parent(TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the cursor to the next sibling of its current node.
|
|
||||||
*
|
|
||||||
* This returns `true` if the cursor successfully moved, and returns `false`
|
|
||||||
* if there was no next sibling node.
|
|
||||||
*/
|
|
||||||
bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the cursor to the first child of its current node.
|
|
||||||
*
|
|
||||||
* This returns `true` if the cursor successfully moved, and returns `false`
|
|
||||||
* if there were no children.
|
|
||||||
*/
|
|
||||||
bool ts_tree_cursor_goto_first_child(TSTreeCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the cursor to the first child of its current node that extends beyond
|
|
||||||
* the given byte offset or point.
|
|
||||||
*
|
|
||||||
* This returns the index of the child node if one was found, and returns -1
|
|
||||||
* if no such child was found.
|
|
||||||
*/
|
|
||||||
int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *, uint32_t);
|
|
||||||
int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *, TSPoint);
|
|
||||||
|
|
||||||
TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *);
|
|
||||||
|
|
||||||
/*******************/
|
|
||||||
/* Section - Query */
|
|
||||||
/*******************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new query from a string containing one or more S-expression
|
|
||||||
* patterns. The query is associated with a particular language, and can
|
|
||||||
* only be run on syntax nodes parsed with that language.
|
|
||||||
*
|
|
||||||
* If all of the given patterns are valid, this returns a `TSQuery`.
|
|
||||||
* If a pattern is invalid, this returns `NULL`, and provides two pieces
|
|
||||||
* of information about the problem:
|
|
||||||
* 1. The byte offset of the error is written to the `error_offset` parameter.
|
|
||||||
* 2. The type of error is written to the `error_type` parameter.
|
|
||||||
*/
|
|
||||||
TSQuery *ts_query_new(
|
|
||||||
const TSLanguage *language,
|
|
||||||
const char *source,
|
|
||||||
uint32_t source_len,
|
|
||||||
uint32_t *error_offset,
|
|
||||||
TSQueryError *error_type
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a query, freeing all of the memory that it used.
|
|
||||||
*/
|
|
||||||
void ts_query_delete(TSQuery *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of patterns, captures, or string literals in the query.
|
|
||||||
*/
|
|
||||||
uint32_t ts_query_pattern_count(const TSQuery *);
|
|
||||||
uint32_t ts_query_capture_count(const TSQuery *);
|
|
||||||
uint32_t ts_query_string_count(const TSQuery *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the byte offset where the given pattern starts in the query's source.
|
|
||||||
*
|
|
||||||
* This can be useful when combining queries by concatenating their source
|
|
||||||
* code strings.
|
|
||||||
*/
|
|
||||||
uint32_t ts_query_start_byte_for_pattern(const TSQuery *, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all of the predicates for the given pattern in the query.
|
|
||||||
*
|
|
||||||
* The predicates are represented as a single array of steps. There are three
|
|
||||||
* types of steps in this array, which correspond to the three legal values for
|
|
||||||
* the `type` field:
|
|
||||||
* - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names
|
|
||||||
* of captures. Their `value_id` can be used with the
|
|
||||||
* `ts_query_capture_name_for_id` function to obtain the name of the capture.
|
|
||||||
* - `TSQueryPredicateStepTypeString` - Steps with this type represent literal
|
|
||||||
* strings. Their `value_id` can be used with the
|
|
||||||
* `ts_query_string_value_for_id` function to obtain their string value.
|
|
||||||
* - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels*
|
|
||||||
* that represent the end of an individual predicate. If a pattern has two
|
|
||||||
* predicates, then there will be two steps with this `type` in the array.
|
|
||||||
*/
|
|
||||||
const TSQueryPredicateStep *ts_query_predicates_for_pattern(
|
|
||||||
const TSQuery *self,
|
|
||||||
uint32_t pattern_index,
|
|
||||||
uint32_t *length
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the given pattern in the query has a single root node.
|
|
||||||
*/
|
|
||||||
bool ts_query_is_pattern_rooted(const TSQuery *self, uint32_t pattern_index);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the given pattern in the query is 'non local'.
|
|
||||||
*
|
|
||||||
* A non-local pattern has multiple root nodes and can match within a
|
|
||||||
* repeating sequence of nodes, as specified by the grammar. Non-local
|
|
||||||
* patterns disable certain optimizations that would otherwise be possible
|
|
||||||
* when executing a query on a specific range of a syntax tree.
|
|
||||||
*/
|
|
||||||
bool ts_query_is_pattern_non_local(const TSQuery *self, uint32_t pattern_index);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if a given pattern is guaranteed to match once a given step is reached.
|
|
||||||
* The step is specified by its byte offset in the query's source code.
|
|
||||||
*/
|
|
||||||
bool ts_query_is_pattern_guaranteed_at_step(const TSQuery *self, uint32_t byte_offset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name and length of one of the query's captures, or one of the
|
|
||||||
* query's string literals. Each capture and string is associated with a
|
|
||||||
* numeric id based on the order that it appeared in the query's source.
|
|
||||||
*/
|
|
||||||
const char *ts_query_capture_name_for_id(
|
|
||||||
const TSQuery *,
|
|
||||||
uint32_t id,
|
|
||||||
uint32_t *length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the quantifier of the query's captures. Each capture is * associated
|
|
||||||
* with a numeric id based on the order that it appeared in the query's source.
|
|
||||||
*/
|
|
||||||
TSQuantifier ts_query_capture_quantifier_for_id(
|
|
||||||
const TSQuery *,
|
|
||||||
uint32_t pattern_id,
|
|
||||||
uint32_t capture_id
|
|
||||||
);
|
|
||||||
|
|
||||||
const char *ts_query_string_value_for_id(
|
|
||||||
const TSQuery *,
|
|
||||||
uint32_t id,
|
|
||||||
uint32_t *length
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable a certain capture within a query.
|
|
||||||
*
|
|
||||||
* This prevents the capture from being returned in matches, and also avoids
|
|
||||||
* any resource usage associated with recording the capture. Currently, there
|
|
||||||
* is no way to undo this.
|
|
||||||
*/
|
|
||||||
void ts_query_disable_capture(TSQuery *, const char *, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable a certain pattern within a query.
|
|
||||||
*
|
|
||||||
* This prevents the pattern from matching and removes most of the overhead
|
|
||||||
* associated with the pattern. Currently, there is no way to undo this.
|
|
||||||
*/
|
|
||||||
void ts_query_disable_pattern(TSQuery *, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new cursor for executing a given query.
|
|
||||||
*
|
|
||||||
* The cursor stores the state that is needed to iteratively search
|
|
||||||
* for matches. To use the query cursor, first call `ts_query_cursor_exec`
|
|
||||||
* to start running a given query on a given syntax node. Then, there are
|
|
||||||
* two options for consuming the results of the query:
|
|
||||||
* 1. Repeatedly call `ts_query_cursor_next_match` to iterate over all of the
|
|
||||||
* *matches* in the order that they were found. Each match contains the
|
|
||||||
* index of the pattern that matched, and an array of captures. Because
|
|
||||||
* multiple patterns can match the same set of nodes, one match may contain
|
|
||||||
* captures that appear *before* some of the captures from a previous match.
|
|
||||||
* 2. Repeatedly call `ts_query_cursor_next_capture` to iterate over all of the
|
|
||||||
* individual *captures* in the order that they appear. This is useful if
|
|
||||||
* don't care about which pattern matched, and just want a single ordered
|
|
||||||
* sequence of captures.
|
|
||||||
*
|
|
||||||
* If you don't care about consuming all of the results, you can stop calling
|
|
||||||
* `ts_query_cursor_next_match` or `ts_query_cursor_next_capture` at any point.
|
|
||||||
* You can then start executing another query on another node by calling
|
|
||||||
* `ts_query_cursor_exec` again.
|
|
||||||
*/
|
|
||||||
TSQueryCursor *ts_query_cursor_new(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a query cursor, freeing all of the memory that it used.
|
|
||||||
*/
|
|
||||||
void ts_query_cursor_delete(TSQueryCursor *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start running a given query on a given node.
|
|
||||||
*/
|
|
||||||
void ts_query_cursor_exec(TSQueryCursor *, const TSQuery *, TSNode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manage the maximum number of in-progress matches allowed by this query
|
|
||||||
* cursor.
|
|
||||||
*
|
|
||||||
* Query cursors have an optional maximum capacity for storing lists of
|
|
||||||
* in-progress captures. If this capacity is exceeded, then the
|
|
||||||
* earliest-starting match will silently be dropped to make room for further
|
|
||||||
* matches. This maximum capacity is optional — by default, query cursors allow
|
|
||||||
* any number of pending matches, dynamically allocating new space for them as
|
|
||||||
* needed as the query is executed.
|
|
||||||
*/
|
|
||||||
bool ts_query_cursor_did_exceed_match_limit(const TSQueryCursor *);
|
|
||||||
uint32_t ts_query_cursor_match_limit(const TSQueryCursor *);
|
|
||||||
void ts_query_cursor_set_match_limit(TSQueryCursor *, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the range of bytes or (row, column) positions in which the query
|
|
||||||
* will be executed.
|
|
||||||
*/
|
|
||||||
void ts_query_cursor_set_byte_range(TSQueryCursor *, uint32_t, uint32_t);
|
|
||||||
void ts_query_cursor_set_point_range(TSQueryCursor *, TSPoint, TSPoint);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Advance to the next match of the currently running query.
|
|
||||||
*
|
|
||||||
* If there is a match, write it to `*match` and return `true`.
|
|
||||||
* Otherwise, return `false`.
|
|
||||||
*/
|
|
||||||
bool ts_query_cursor_next_match(TSQueryCursor *, TSQueryMatch *match);
|
|
||||||
void ts_query_cursor_remove_match(TSQueryCursor *, uint32_t id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Advance to the next capture of the currently running query.
|
|
||||||
*
|
|
||||||
* If there is a capture, write its match to `*match` and its index within
|
|
||||||
* the matche's capture list to `*capture_index`. Otherwise, return `false`.
|
|
||||||
*/
|
|
||||||
bool ts_query_cursor_next_capture(
|
|
||||||
TSQueryCursor *,
|
|
||||||
TSQueryMatch *match,
|
|
||||||
uint32_t *capture_index
|
|
||||||
);
|
|
||||||
|
|
||||||
/**********************/
|
|
||||||
/* Section - Language */
|
|
||||||
/**********************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of distinct node types in the language.
|
|
||||||
*/
|
|
||||||
uint32_t ts_language_symbol_count(const TSLanguage *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a node type string for the given numerical id.
|
|
||||||
*/
|
|
||||||
const char *ts_language_symbol_name(const TSLanguage *, TSSymbol);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the numerical id for the given node type string.
|
|
||||||
*/
|
|
||||||
TSSymbol ts_language_symbol_for_name(
|
|
||||||
const TSLanguage *self,
|
|
||||||
const char *string,
|
|
||||||
uint32_t length,
|
|
||||||
bool is_named
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of distinct field names in the language.
|
|
||||||
*/
|
|
||||||
uint32_t ts_language_field_count(const TSLanguage *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the field name string for the given numerical id.
|
|
||||||
*/
|
|
||||||
const char *ts_language_field_name_for_id(const TSLanguage *, TSFieldId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the numerical id for the given field name string.
|
|
||||||
*/
|
|
||||||
TSFieldId ts_language_field_id_for_name(const TSLanguage *, const char *, uint32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the given node type id belongs to named nodes, anonymous nodes,
|
|
||||||
* or a hidden nodes.
|
|
||||||
*
|
|
||||||
* See also `ts_node_is_named`. Hidden nodes are never returned from the API.
|
|
||||||
*/
|
|
||||||
TSSymbolType ts_language_symbol_type(const TSLanguage *, TSSymbol);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the ABI version number for this language. This version number is used
|
|
||||||
* to ensure that languages were generated by a compatible version of
|
|
||||||
* Tree-sitter.
|
|
||||||
*
|
|
||||||
* See also `ts_parser_set_language`.
|
|
||||||
*/
|
|
||||||
uint32_t ts_language_version(const TSLanguage *);
|
|
||||||
|
|
||||||
/**********************************/
|
|
||||||
/* Section - Global Configuration */
|
|
||||||
/**********************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the allocation functions used by the library.
|
|
||||||
*
|
|
||||||
* By default, Tree-sitter uses the standard libc allocation functions,
|
|
||||||
* but aborts the process when an allocation fails. This function lets
|
|
||||||
* you supply alternative allocation functions at runtime.
|
|
||||||
*
|
|
||||||
* If you pass `NULL` for any parameter, Tree-sitter will switch back to
|
|
||||||
* its default implementation of that function.
|
|
||||||
*
|
|
||||||
* If you call this function after the library has already been used, then
|
|
||||||
* you must ensure that either:
|
|
||||||
* 1. All the existing objects have been freed.
|
|
||||||
* 2. The new allocator shares its state with the old one, so it is capable
|
|
||||||
* of freeing memory that was allocated by the old allocator.
|
|
||||||
*/
|
|
||||||
void ts_set_allocator(
|
|
||||||
void *(*new_malloc)(size_t),
|
|
||||||
void *(*new_calloc)(size_t, size_t),
|
|
||||||
void *(*new_realloc)(void *, size_t),
|
|
||||||
void (*new_free)(void *)
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_API_H_
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue