diff --git a/.gitignore b/.gitignore index ff7f4c3..3e8c1bf 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ test*.c* **/x64 *.user *.filters +*.tmp +server.bin \ No newline at end of file diff --git a/7iut1mxt.shm b/7iut1mxt.shm new file mode 100644 index 0000000..35a0387 Binary files /dev/null and b/7iut1mxt.shm differ diff --git a/Makefile b/Makefile index fef8c50..bac0dda 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,4 @@ -all: - g++ mmw.cpp --std=c++1z -shared -fPIC -Ofast -march=native -g0 -s -o mmw.so -avx512: - g++ mmw.cpp --std=c++1z -shared -fPIC -Ofast -mavx512f -g0 -s -o mmw.so -debug: - g++ mmw.cpp --std=c++1z -shared -fPIC -O0 -march=native -g3 -o mmw.so -clean: - rm mmw.so -rf +snippet: + g++ -shared --std=c++1z out.cpp -O3 -march=native -o dll.so +clean: + rm *.shm -rf \ No newline at end of file diff --git a/Makefile.old b/Makefile.old new file mode 100644 index 0000000..fef8c50 --- /dev/null +++ b/Makefile.old @@ -0,0 +1,8 @@ +all: + g++ mmw.cpp --std=c++1z -shared -fPIC -Ofast -march=native -g0 -s -o mmw.so +avx512: + g++ mmw.cpp --std=c++1z -shared -fPIC -Ofast -mavx512f -g0 -s -o mmw.so +debug: + g++ mmw.cpp --std=c++1z -shared -fPIC -O0 -march=native -g3 -o mmw.so +clean: + rm mmw.so -rf diff --git a/README.md b/README.md index acf25f4..8567239 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # AQuery Compiler -AQuery Compiler that compiles AQuery into [K9](https://shakti.com/). +AQuery Compiler that compiles AQuery into [c](https://shakti.com/). Frontend built on top of [mo-sql-parsing](https://github.com/klahnakoski/mo-sql-parsing). ## Roadmap - [x] SQL Parser -> AQuery Parser - [ ] Data acquisition/output from/to csv file (By Jan. 21) -- -> AQuery-K9 Compiler +- -> AQuery-c Compiler - Simple query (By Jan. 21) - [ ] Nested queries (Jan. 28) - [ ] -> Optimizing Compiler diff --git a/Untitled-1.ipynb b/Untitled-1.ipynb new file mode 100644 index 0000000..99b078c --- /dev/null +++ b/Untitled-1.ipynb @@ -0,0 +1,61 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0, 1\n", + "1, 1\n", + "1, 2\n", + "1, 2\n" + ] + } + ], + "source": [ + "class A:\n", + " def s(self, *_):\n", + " print(\"A\")\n", + "\n", + "class B(A):\n", + " def s(self, a, b = 1, *_):\n", + " print(f'{a}, {b}')\n", + "\n", + "t = B()\n", + "t.s(0)\n", + "t.s(1)\n", + "t.s(1,2)\n", + "t.s(1,2,3)" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + }, + "kernelspec": { + "display_name": "Python 3.10.2 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.2" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/_server.bin b/_server.bin new file mode 100644 index 0000000..4d95349 Binary files /dev/null and b/_server.bin differ diff --git a/aquery_parser/sql_parser.py b/aquery_parser/sql_parser.py index 17790aa..95f7beb 100644 --- a/aquery_parser/sql_parser.py +++ b/aquery_parser/sql_parser.py @@ -64,7 +64,7 @@ def parser(literal_string, ident, sqlserver=False): var_name = ~RESERVED + ident - inline_kblock = (L_INLINE + SkipTo(R_INLINE, include=True))("k9") + inline_kblock = (L_INLINE + SkipTo(R_INLINE, include=True))("c") # EXPRESSIONS expr = Forward() column_type, column_definition, column_def_references = get_column_type( diff --git a/csv.h b/csv.h new file mode 100644 index 0000000..c5cb5bc --- /dev/null +++ b/csv.h @@ -0,0 +1,1273 @@ +// Copyright: (2012-2015) Ben Strasser +// License: BSD-3 +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef CSV_H +#define CSV_H + +#include +#include +#include +#include +#include +#include +#include +#ifndef CSV_IO_NO_THREAD +#include +#include +#include +#endif +#include +#include +#include +#include +#include + +namespace io{ + //////////////////////////////////////////////////////////////////////////// + // LineReader // + //////////////////////////////////////////////////////////////////////////// + + namespace error{ + struct base : std::exception{ + virtual void format_error_message()const = 0; + + const char*what()const noexcept override{ + format_error_message(); + return error_message_buffer; + } + + mutable char error_message_buffer[512]; + }; + + const int max_file_name_length = 255; + + struct with_file_name{ + with_file_name(){ + std::memset(file_name, 0, sizeof(file_name)); + } + + void set_file_name(const char*file_name){ + if(file_name != nullptr){ + // This call to strncpy has parenthesis around it + // to silence the GCC -Wstringop-truncation warning + (strncpy(this->file_name, file_name, sizeof(this->file_name))); + this->file_name[sizeof(this->file_name)-1] = '\0'; + }else{ + this->file_name[0] = '\0'; + } + } + + char file_name[max_file_name_length+1]; + }; + + struct with_file_line{ + with_file_line(){ + file_line = -1; + } + + void set_file_line(int file_line){ + this->file_line = file_line; + } + + int file_line; + }; + + struct with_errno{ + with_errno(){ + errno_value = 0; + } + + void set_errno(int errno_value){ + this->errno_value = errno_value; + } + + int errno_value; + }; + + struct can_not_open_file : + base, + with_file_name, + with_errno{ + void format_error_message()const override{ + if(errno_value != 0) + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Can not open file \"%s\" because \"%s\"." + , file_name, std::strerror(errno_value)); + else + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Can not open file \"%s\"." + , file_name); + } + }; + + struct line_length_limit_exceeded : + base, + with_file_name, + with_file_line{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Line number %d in file \"%s\" exceeds the maximum length of 2^24-1." + , file_line, file_name); + } + }; + } + + class ByteSourceBase{ + public: + virtual int read(char*buffer, int size)=0; + virtual ~ByteSourceBase(){} + }; + + namespace detail{ + + class OwningStdIOByteSourceBase : public ByteSourceBase{ + public: + explicit OwningStdIOByteSourceBase(FILE*file):file(file){ + // Tell the std library that we want to do the buffering ourself. + std::setvbuf(file, 0, _IONBF, 0); + } + + int read(char*buffer, int size){ + return std::fread(buffer, 1, size, file); + } + + ~OwningStdIOByteSourceBase(){ + std::fclose(file); + } + + private: + FILE*file; + }; + + class NonOwningIStreamByteSource : public ByteSourceBase{ + public: + explicit NonOwningIStreamByteSource(std::istream&in):in(in){} + + int read(char*buffer, int size){ + in.read(buffer, size); + return in.gcount(); + } + + ~NonOwningIStreamByteSource(){} + + private: + std::istream∈ + }; + + class NonOwningStringByteSource : public ByteSourceBase{ + public: + NonOwningStringByteSource(const char*str, long long size):str(str), remaining_byte_count(size){} + + int read(char*buffer, int desired_byte_count){ + int to_copy_byte_count = desired_byte_count; + if(remaining_byte_count < to_copy_byte_count) + to_copy_byte_count = remaining_byte_count; + std::memcpy(buffer, str, to_copy_byte_count); + remaining_byte_count -= to_copy_byte_count; + str += to_copy_byte_count; + return to_copy_byte_count; + } + + ~NonOwningStringByteSource(){} + + private: + const char*str; + long long remaining_byte_count; + }; + + #ifndef CSV_IO_NO_THREAD + class AsynchronousReader{ + public: + void init(std::unique_ptrarg_byte_source){ + std::unique_lockguard(lock); + byte_source = std::move(arg_byte_source); + desired_byte_count = -1; + termination_requested = false; + worker = std::thread( + [&]{ + std::unique_lockguard(lock); + try{ + for(;;){ + read_requested_condition.wait( + guard, + [&]{ + return desired_byte_count != -1 || termination_requested; + } + ); + if(termination_requested) + return; + + read_byte_count = byte_source->read(buffer, desired_byte_count); + desired_byte_count = -1; + if(read_byte_count == 0) + break; + read_finished_condition.notify_one(); + } + }catch(...){ + read_error = std::current_exception(); + } + read_finished_condition.notify_one(); + } + ); + } + + bool is_valid()const{ + return byte_source != nullptr; + } + + void start_read(char*arg_buffer, int arg_desired_byte_count){ + std::unique_lockguard(lock); + buffer = arg_buffer; + desired_byte_count = arg_desired_byte_count; + read_byte_count = -1; + read_requested_condition.notify_one(); + } + + int finish_read(){ + std::unique_lockguard(lock); + read_finished_condition.wait( + guard, + [&]{ + return read_byte_count != -1 || read_error; + } + ); + if(read_error) + std::rethrow_exception(read_error); + else + return read_byte_count; + } + + ~AsynchronousReader(){ + if(byte_source != nullptr){ + { + std::unique_lockguard(lock); + termination_requested = true; + } + read_requested_condition.notify_one(); + worker.join(); + } + } + + private: + std::unique_ptrbyte_source; + + std::thread worker; + + bool termination_requested; + std::exception_ptr read_error; + char*buffer; + int desired_byte_count; + int read_byte_count; + + std::mutex lock; + std::condition_variable read_finished_condition; + std::condition_variable read_requested_condition; + }; + #endif + + class SynchronousReader{ + public: + void init(std::unique_ptrarg_byte_source){ + byte_source = std::move(arg_byte_source); + } + + bool is_valid()const{ + return byte_source != nullptr; + } + + void start_read(char*arg_buffer, int arg_desired_byte_count){ + buffer = arg_buffer; + desired_byte_count = arg_desired_byte_count; + } + + int finish_read(){ + return byte_source->read(buffer, desired_byte_count); + } + private: + std::unique_ptrbyte_source; + char*buffer; + int desired_byte_count; + }; + } + + class LineReader{ + private: + static const int block_len = 1<<20; + std::unique_ptrbuffer; // must be constructed before (and thus destructed after) the reader! + #ifdef CSV_IO_NO_THREAD + detail::SynchronousReader reader; + #else + detail::AsynchronousReader reader; + #endif + int data_begin; + int data_end; + + char file_name[error::max_file_name_length+1]; + unsigned file_line; + + static std::unique_ptr open_file(const char*file_name){ + // We open the file in binary mode as it makes no difference under *nix + // and under Windows we handle \r\n newlines ourself. + FILE*file = std::fopen(file_name, "rb"); + if(file == 0){ + int x = errno; // store errno as soon as possible, doing it after constructor call can fail. + error::can_not_open_file err; + err.set_errno(x); + err.set_file_name(file_name); + throw err; + } + return std::unique_ptr(new detail::OwningStdIOByteSourceBase(file)); + } + + void init(std::unique_ptrbyte_source){ + file_line = 0; + + buffer = std::unique_ptr(new char[3*block_len]); + data_begin = 0; + data_end = byte_source->read(buffer.get(), 2*block_len); + + // Ignore UTF-8 BOM + if(data_end >= 3 && buffer[0] == '\xEF' && buffer[1] == '\xBB' && buffer[2] == '\xBF') + data_begin = 3; + + if(data_end == 2*block_len){ + reader.init(std::move(byte_source)); + reader.start_read(buffer.get() + 2*block_len, block_len); + } + } + + public: + LineReader() = delete; + LineReader(const LineReader&) = delete; + LineReader&operator=(const LineReader&) = delete; + + explicit LineReader(const char*file_name){ + set_file_name(file_name); + init(open_file(file_name)); + } + + explicit LineReader(const std::string&file_name){ + set_file_name(file_name.c_str()); + init(open_file(file_name.c_str())); + } + + LineReader(const char*file_name, std::unique_ptrbyte_source){ + set_file_name(file_name); + init(std::move(byte_source)); + } + + LineReader(const std::string&file_name, std::unique_ptrbyte_source){ + set_file_name(file_name.c_str()); + init(std::move(byte_source)); + } + + LineReader(const char*file_name, const char*data_begin, const char*data_end){ + set_file_name(file_name); + init(std::unique_ptr(new detail::NonOwningStringByteSource(data_begin, data_end-data_begin))); + } + + LineReader(const std::string&file_name, const char*data_begin, const char*data_end){ + set_file_name(file_name.c_str()); + init(std::unique_ptr(new detail::NonOwningStringByteSource(data_begin, data_end-data_begin))); + } + + LineReader(const char*file_name, FILE*file){ + set_file_name(file_name); + init(std::unique_ptr(new detail::OwningStdIOByteSourceBase(file))); + } + + LineReader(const std::string&file_name, FILE*file){ + set_file_name(file_name.c_str()); + init(std::unique_ptr(new detail::OwningStdIOByteSourceBase(file))); + } + + LineReader(const char*file_name, std::istream&in){ + set_file_name(file_name); + init(std::unique_ptr(new detail::NonOwningIStreamByteSource(in))); + } + + LineReader(const std::string&file_name, std::istream&in){ + set_file_name(file_name.c_str()); + init(std::unique_ptr(new detail::NonOwningIStreamByteSource(in))); + } + + void set_file_name(const std::string&file_name){ + set_file_name(file_name.c_str()); + } + + void set_file_name(const char*file_name){ + if(file_name != nullptr){ + strncpy(this->file_name, file_name, sizeof(this->file_name)); + this->file_name[sizeof(this->file_name)-1] = '\0'; + }else{ + this->file_name[0] = '\0'; + } + } + + const char*get_truncated_file_name()const{ + return file_name; + } + + void set_file_line(unsigned file_line){ + this->file_line = file_line; + } + + unsigned get_file_line()const{ + return file_line; + } + + char*next_line(){ + if(data_begin == data_end) + return nullptr; + + ++file_line; + + assert(data_begin < data_end); + assert(data_end <= block_len*2); + + if(data_begin >= block_len){ + std::memcpy(buffer.get(), buffer.get()+block_len, block_len); + data_begin -= block_len; + data_end -= block_len; + if(reader.is_valid()) + { + data_end += reader.finish_read(); + std::memcpy(buffer.get()+block_len, buffer.get()+2*block_len, block_len); + reader.start_read(buffer.get() + 2*block_len, block_len); + } + } + + int line_end = data_begin; + while(line_end != data_end && buffer[line_end] != '\n'){ + ++line_end; + } + + if(line_end - data_begin + 1 > block_len){ + error::line_length_limit_exceeded err; + err.set_file_name(file_name); + err.set_file_line(file_line); + throw err; + } + + if(line_end != data_end && buffer[line_end] == '\n'){ + buffer[line_end] = '\0'; + }else{ + // some files are missing the newline at the end of the + // last line + ++data_end; + buffer[line_end] = '\0'; + } + + // handle windows \r\n-line breaks + if(line_end != data_begin && buffer[line_end-1] == '\r') + buffer[line_end-1] = '\0'; + + char*ret = buffer.get() + data_begin; + data_begin = line_end+1; + return ret; + } + }; + + + //////////////////////////////////////////////////////////////////////////// + // CSV // + //////////////////////////////////////////////////////////////////////////// + + namespace error{ + const int max_column_name_length = 63; + struct with_column_name{ + with_column_name(){ + std::memset(column_name, 0, max_column_name_length+1); + } + + void set_column_name(const char*column_name){ + if(column_name != nullptr){ + std::strncpy(this->column_name, column_name, max_column_name_length); + this->column_name[max_column_name_length] = '\0'; + }else{ + this->column_name[0] = '\0'; + } + } + + char column_name[max_column_name_length+1]; + }; + + + const int max_column_content_length = 63; + + struct with_column_content{ + with_column_content(){ + std::memset(column_content, 0, max_column_content_length+1); + } + + void set_column_content(const char*column_content){ + if(column_content != nullptr){ + std::strncpy(this->column_content, column_content, max_column_content_length); + this->column_content[max_column_content_length] = '\0'; + }else{ + this->column_content[0] = '\0'; + } + } + + char column_content[max_column_content_length+1]; + }; + + + struct extra_column_in_header : + base, + with_file_name, + with_column_name{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(Extra column "%s" in header of file "%s".)" + , column_name, file_name); + } + }; + + struct missing_column_in_header : + base, + with_file_name, + with_column_name{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(Missing column "%s" in header of file "%s".)" + , column_name, file_name); + } + }; + + struct duplicated_column_in_header : + base, + with_file_name, + with_column_name{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(Duplicated column "%s" in header of file "%s".)" + , column_name, file_name); + } + }; + + struct header_missing : + base, + with_file_name{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Header missing in file \"%s\"." + , file_name); + } + }; + + struct too_few_columns : + base, + with_file_name, + with_file_line{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Too few columns in line %d in file \"%s\"." + , file_line, file_name); + } + }; + + struct too_many_columns : + base, + with_file_name, + with_file_line{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Too many columns in line %d in file \"%s\"." + , file_line, file_name); + } + }; + + struct escaped_string_not_closed : + base, + with_file_name, + with_file_line{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + "Escaped string was not closed in line %d in file \"%s\"." + , file_line, file_name); + } + }; + + struct integer_must_be_positive : + base, + with_file_name, + with_file_line, + with_column_name, + with_column_content{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(The integer "%s" must be positive or 0 in column "%s" in file "%s" in line "%d".)" + , column_content, column_name, file_name, file_line); + } + }; + + struct no_digit : + base, + with_file_name, + with_file_line, + with_column_name, + with_column_content{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(The integer "%s" contains an invalid digit in column "%s" in file "%s" in line "%d".)" + , column_content, column_name, file_name, file_line); + } + }; + + struct integer_overflow : + base, + with_file_name, + with_file_line, + with_column_name, + with_column_content{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(The integer "%s" overflows in column "%s" in file "%s" in line "%d".)" + , column_content, column_name, file_name, file_line); + } + }; + + struct integer_underflow : + base, + with_file_name, + with_file_line, + with_column_name, + with_column_content{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(The integer "%s" underflows in column "%s" in file "%s" in line "%d".)" + , column_content, column_name, file_name, file_line); + } + }; + + struct invalid_single_character : + base, + with_file_name, + with_file_line, + with_column_name, + with_column_content{ + void format_error_message()const override{ + std::snprintf(error_message_buffer, sizeof(error_message_buffer), + R"(The content "%s" of column "%s" in file "%s" in line "%d" is not a single character.)" + , column_content, column_name, file_name, file_line); + } + }; + } + + using ignore_column = unsigned int; + static const ignore_column ignore_no_column = 0; + static const ignore_column ignore_extra_column = 1; + static const ignore_column ignore_missing_column = 2; + + template + struct trim_chars{ + private: + constexpr static bool is_trim_char(char){ + return false; + } + + template + constexpr static bool is_trim_char(char c, char trim_char, OtherTrimChars...other_trim_chars){ + return c == trim_char || is_trim_char(c, other_trim_chars...); + } + + public: + static void trim(char*&str_begin, char*&str_end){ + while(str_begin != str_end && is_trim_char(*str_begin, trim_char_list...)) + ++str_begin; + while(str_begin != str_end && is_trim_char(*(str_end-1), trim_char_list...)) + --str_end; + *str_end = '\0'; + } + }; + + + struct no_comment{ + static bool is_comment(const char*){ + return false; + } + }; + + template + struct single_line_comment{ + private: + constexpr static bool is_comment_start_char(char){ + return false; + } + + template + constexpr static bool is_comment_start_char(char c, char comment_start_char, OtherCommentStartChars...other_comment_start_chars){ + return c == comment_start_char || is_comment_start_char(c, other_comment_start_chars...); + } + + public: + + static bool is_comment(const char*line){ + return is_comment_start_char(*line, comment_start_char_list...); + } + }; + + struct empty_line_comment{ + static bool is_comment(const char*line){ + if(*line == '\0') + return true; + while(*line == ' ' || *line == '\t'){ + ++line; + if(*line == 0) + return true; + } + return false; + } + }; + + template + struct single_and_empty_line_comment{ + static bool is_comment(const char*line){ + return single_line_comment::is_comment(line) || empty_line_comment::is_comment(line); + } + }; + + template + struct no_quote_escape{ + static const char*find_next_column_end(const char*col_begin){ + while(*col_begin != sep && *col_begin != '\0') + ++col_begin; + return col_begin; + } + + static void unescape(char*&, char*&){ + + } + }; + + template + struct double_quote_escape{ + static const char*find_next_column_end(const char*col_begin){ + while(*col_begin != sep && *col_begin != '\0') + if(*col_begin != quote) + ++col_begin; + else{ + do{ + ++col_begin; + while(*col_begin != quote){ + if(*col_begin == '\0') + throw error::escaped_string_not_closed(); + ++col_begin; + } + ++col_begin; + }while(*col_begin == quote); + } + return col_begin; + } + + static void unescape(char*&col_begin, char*&col_end){ + if(col_end - col_begin >= 2){ + if(*col_begin == quote && *(col_end-1) == quote){ + ++col_begin; + --col_end; + char*out = col_begin; + for(char*in = col_begin; in!=col_end; ++in){ + if(*in == quote && (in+1) != col_end && *(in+1) == quote){ + ++in; + } + *out = *in; + ++out; + } + col_end = out; + *col_end = '\0'; + } + } + + } + }; + + struct throw_on_overflow{ + template + static void on_overflow(T&){ + throw error::integer_overflow(); + } + + template + static void on_underflow(T&){ + throw error::integer_underflow(); + } + }; + + struct ignore_overflow{ + template + static void on_overflow(T&){} + + template + static void on_underflow(T&){} + }; + + struct set_to_max_on_overflow{ + template + static void on_overflow(T&x){ + // using (std::numeric_limits::max) instead of std::numeric_limits::max + // to make code including windows.h with its max macro happy + x = (std::numeric_limits::max)(); + } + + template + static void on_underflow(T&x){ + x = (std::numeric_limits::min)(); + } + }; + + + namespace detail{ + template + void chop_next_column( + char*&line, char*&col_begin, char*&col_end + ){ + assert(line != nullptr); + + col_begin = line; + // the col_begin + (... - col_begin) removes the constness + col_end = col_begin + (quote_policy::find_next_column_end(col_begin) - col_begin); + + if(*col_end == '\0'){ + line = nullptr; + }else{ + *col_end = '\0'; + line = col_end + 1; + } + } + + template + void parse_line( + char*line, + char**sorted_col, + const std::vector&col_order + ){ + for (int i : col_order) { + if(line == nullptr) + throw ::io::error::too_few_columns(); + char*col_begin, *col_end; + chop_next_column(line, col_begin, col_end); + + if (i != -1) { + trim_policy::trim(col_begin, col_end); + quote_policy::unescape(col_begin, col_end); + + sorted_col[i] = col_begin; + } + } + if(line != nullptr) + throw ::io::error::too_many_columns(); + } + + template + void parse_header_line( + char*line, + std::vector&col_order, + const std::string*col_name, + ignore_column ignore_policy + ){ + col_order.clear(); + + bool found[column_count]; + std::fill(found, found + column_count, false); + while(line){ + char*col_begin,*col_end; + chop_next_column(line, col_begin, col_end); + + trim_policy::trim(col_begin, col_end); + quote_policy::unescape(col_begin, col_end); + + for(unsigned i=0; i + void parse(char*col, char &x){ + if(!*col) + throw error::invalid_single_character(); + x = *col; + ++col; + if(*col) + throw error::invalid_single_character(); + } + + template + void parse(char*col, std::string&x){ + x = col; + } + + template + void parse(char*col, const char*&x){ + x = col; + } + + template + void parse(char*col, char*&x){ + x = col; + } + + template + void parse_unsigned_integer(const char*col, T&x){ + x = 0; + while(*col != '\0'){ + if('0' <= *col && *col <= '9'){ + T y = *col - '0'; + if(x > ((std::numeric_limits::max)()-y)/10){ + overflow_policy::on_overflow(x); + return; + } + x = 10*x+y; + }else + throw error::no_digit(); + ++col; + } + } + + templatevoid parse(char*col, unsigned char &x) + {parse_unsigned_integer(col, x);} + templatevoid parse(char*col, unsigned short &x) + {parse_unsigned_integer(col, x);} + templatevoid parse(char*col, unsigned int &x) + {parse_unsigned_integer(col, x);} + templatevoid parse(char*col, unsigned long &x) + {parse_unsigned_integer(col, x);} + templatevoid parse(char*col, unsigned long long &x) + {parse_unsigned_integer(col, x);} + + template + void parse_signed_integer(const char*col, T&x){ + if(*col == '-'){ + ++col; + + x = 0; + while(*col != '\0'){ + if('0' <= *col && *col <= '9'){ + T y = *col - '0'; + if(x < ((std::numeric_limits::min)()+y)/10){ + overflow_policy::on_underflow(x); + return; + } + x = 10*x-y; + }else + throw error::no_digit(); + ++col; + } + return; + }else if(*col == '+') + ++col; + parse_unsigned_integer(col, x); + } + + templatevoid parse(char*col, signed char &x) + {parse_signed_integer(col, x);} + templatevoid parse(char*col, signed short &x) + {parse_signed_integer(col, x);} + templatevoid parse(char*col, signed int &x) + {parse_signed_integer(col, x);} + templatevoid parse(char*col, signed long &x) + {parse_signed_integer(col, x);} + templatevoid parse(char*col, signed long long &x) + {parse_signed_integer(col, x);} + + template + void parse_float(const char*col, T&x){ + bool is_neg = false; + if(*col == '-'){ + is_neg = true; + ++col; + }else if(*col == '+') + ++col; + + x = 0; + while('0' <= *col && *col <= '9'){ + int y = *col - '0'; + x *= 10; + x += y; + ++col; + } + + if(*col == '.'|| *col == ','){ + ++col; + T pos = 1; + while('0' <= *col && *col <= '9'){ + pos /= 10; + int y = *col - '0'; + ++col; + x += y*pos; + } + } + + if(*col == 'e' || *col == 'E'){ + ++col; + int e; + + parse_signed_integer(col, e); + + if(e != 0){ + T base; + if(e < 0){ + base = T(0.1); + e = -e; + }else{ + base = T(10); + } + + while(e != 1){ + if((e & 1) == 0){ + base = base*base; + e >>= 1; + }else{ + x *= base; + --e; + } + } + x *= base; + } + }else{ + if(*col != '\0') + throw error::no_digit(); + } + + if(is_neg) + x = -x; + } + + template void parse(char*col, float&x) { parse_float(col, x); } + template void parse(char*col, double&x) { parse_float(col, x); } + template void parse(char*col, long double&x) { parse_float(col, x); } + + template + void parse(char*col, T&x){ + // Mute unused variable compiler warning + (void)col; + (void)x; + // GCC evalutes "false" when reading the template and + // "sizeof(T)!=sizeof(T)" only when instantiating it. This is why + // this strange construct is used. + static_assert(sizeof(T)!=sizeof(T), + "Can not parse this type. Only buildin integrals, floats, char, char*, const char* and std::string are supported"); + } + + } + + template, + class quote_policy = no_quote_escape<','>, + class overflow_policy = throw_on_overflow, + class comment_policy = no_comment + > + class CSVReader{ + private: + LineReader in; + + char*row[column_count]; + std::string column_names[column_count]; + + std::vectorcol_order; + + template + void set_column_names(std::string s, ColNames...cols){ + column_names[column_count-sizeof...(ColNames)-1] = std::move(s); + set_column_names(std::forward(cols)...); + } + + void set_column_names(){} + + + public: + CSVReader() = delete; + CSVReader(const CSVReader&) = delete; + CSVReader&operator=(const CSVReader&); + + template + explicit CSVReader(Args&&...args):in(std::forward(args)...){ + std::fill(row, row+column_count, nullptr); + col_order.resize(column_count); + for(unsigned i=0; i + void read_header(ignore_column ignore_policy, ColNames...cols){ + static_assert(sizeof...(ColNames)>=column_count, "not enough column names specified"); + static_assert(sizeof...(ColNames)<=column_count, "too many column names specified"); + try{ + set_column_names(std::forward(cols)...); + + char*line; + do{ + line = in.next_line(); + if(!line) + throw error::header_missing(); + }while(comment_policy::is_comment(line)); + + detail::parse_header_line + + (line, col_order, column_names, ignore_policy); + }catch(error::with_file_name&err){ + err.set_file_name(in.get_truncated_file_name()); + throw; + } + } + + template + void set_header(ColNames...cols){ + static_assert(sizeof...(ColNames)>=column_count, + "not enough column names specified"); + static_assert(sizeof...(ColNames)<=column_count, + "too many column names specified"); + set_column_names(std::forward(cols)...); + std::fill(row, row+column_count, nullptr); + col_order.resize(column_count); + for(unsigned i=0; i + void parse_helper(std::size_t r, T&t, ColType&...cols){ + if(row[r]){ + try{ + try{ + ::io::detail::parse(row[r], t); + }catch(error::with_column_content&err){ + err.set_column_content(row[r]); + throw; + } + }catch(error::with_column_name&err){ + err.set_column_name(column_names[r].c_str()); + throw; + } + } + parse_helper(r+1, cols...); + } + + + public: + template + bool read_row(ColType& ...cols){ + static_assert(sizeof...(ColType)>=column_count, + "not enough columns specified"); + static_assert(sizeof...(ColType)<=column_count, + "too many columns specified"); + try{ + try{ + + char*line; + do{ + line = in.next_line(); + if(!line) + return false; + }while(comment_policy::is_comment(line)); + + detail::parse_line + (line, row, col_order); + + parse_helper(0, cols...); + }catch(error::with_file_name&err){ + err.set_file_name(in.get_truncated_file_name()); + throw; + } + }catch(error::with_file_line&err){ + err.set_file_line(in.get_file_line()); + throw; + } + + return true; + } + }; +} +#endif + diff --git a/engine/ast.py b/engine/ast.py index a348208..9e8dca9 100644 --- a/engine/ast.py +++ b/engine/ast.py @@ -1,24 +1,39 @@ -from typing import List - -from pyparsing import col - from engine.utils import base62uuid # replace column info with this later. class ColRef: - def __init__(self, k9name, _ty, cobj, cnt, table, name, id, compound = False): - self.k9name = k9name + def __init__(self, cname, _ty, cobj, cnt, table:'TableInfo', name, id, compound = False): + self.cname = cname + self.cxt_name = None self.type = _ty self.cobj = cobj self.cnt = cnt self.table = table self.name = name - self.id = id + self.id = id # position in table self.order_pending = None # order_pending self.compound = compound # compound field (list as a field) self.views = [] - self.__arr__ = (k9name, _ty, cobj, cnt, table, name, id) - + self.__arr__ = (cname, _ty, cobj, cnt, table, name, id) + + def reference(self): + cxt = self.table.cxt + self.table.reference() + if self not in cxt.columns_in_context: + counter = 0 + base_name = self.table.table_name + '_' + self.name + if base_name in cxt.columns_in_context.values(): + while (f'{base_name}_{counter}') in cxt.columns_in_context.values(): + counter += 1 + base_name = f'{base_name}_{counter}' + self.cxt_name = base_name + cxt.columns_in_context[self] = base_name + cxt.emit(f'auto& {base_name} = *(ColRef<{self.type}> *)(&{self.table.cxt_name}->colrefs[{self.id}]);') + elif self.cxt_name is None: + self.cxt_name = cxt.columns_in_context[self] + + return self.cxt_name + def __getitem__(self, key): if type(key) is str: return getattr(self, key) @@ -29,7 +44,7 @@ class ColRef: self.__arr__[key] = value def __str__(self): - return self.k9name + return self.cname class TableInfo: @@ -40,7 +55,10 @@ class TableInfo: self.columns_byname = dict() # column_name, type self.columns = [] self.cxt = cxt + self.cxt_name = None self.views = set() + #keep track of temp vars + self.local_vars = dict() self.rec = None self.groupinfo = None self.add_cols(cols) @@ -49,25 +67,47 @@ class TableInfo: self.order = [] # assumptions cxt.tables_byname[self.table_name] = self # construct reverse map + def reference(self): + if self not in self.cxt.tables_in_context: + counter = 0 + base_name = self.table_name + if base_name in self.cxt.tables_in_context.values(): + while (f'{base_name}_{counter}') in self.cxt.tables_in_context.values(): + counter += 1 + base_name = f'{base_name}_{counter}' + self.cxt_name = base_name + self.cxt.tables_in_context[self] = base_name + + type_tags = '<' + for c in self.columns: + type_tags += c.type + ',' + if type_tags.endswith(','): + type_tags = type_tags[:-1] + type_tags += '>' + + self.cxt.emit(f'auto& {base_name} = *(TableInfo{type_tags} *)(cxt->tables[{self.table_name}]);') + def refer_all(self): + for c in self.columns: + c.reference() def add_cols(self, cols, new = True): - for c in cols: - self.add_col(c, new) - def add_col(self, c, new = True): + for i, c in enumerate(cols): + self.add_col(c, new, i) + def add_col(self, c, new = True, i = 0): _ty = c['type'] if new: - k9name = 'c' + base62uuid(7) + cname =f'{self.table_name}->colrefs[{i}].scast()' _ty = _ty if type(c) is ColRef else list(_ty.keys())[0] - col_object = ColRef(k9name, _ty, c, 1, self,c['name'], len(self.columns)) + col_object = ColRef(cname, _ty, c, 1, self,c['name'], len(self.columns)) else: col_object = c - k9name = c.k9name - self.cxt.k9cols_byname[k9name] = col_object + cname = c.cname + self.cxt.ccols_byname[cname] = col_object self.columns_byname[c['name']] = col_object self.columns.append(col_object) def construct(self): for c in self.columns: - self.cxt.emit(f'{c.k9name}:()') + self.cxt.emit(f'{c.cname}:()') @property def n_cols(self): return len(self.columns) @@ -97,18 +137,18 @@ class TableInfo: self.rec.append(col) return col - def get_k9colname_d(self, col_name): - return self.get_col_d(col_name).k9name + def get_ccolname_d(self, col_name): + return self.get_col_d(col_name).cname def get_col(self, col_name): self.materialize_orderbys() col = self.get_col_d(col_name) if type(col.order_pending) is str: - self.cxt.emit_no_flush(f'{col.k9name}:{col.k9name}[{col.order_pending}]') + self.cxt.emit_no_flush(f'{col.cname}:{col.cname}[{col.order_pending}]') col.order_pending = None return col - def get_k9colname(self, col_name): - return self.get_col(col_name).k9name + def get_ccolname(self, col_name): + return self.get_col(col_name).cname def add_alias(self, alias): # TODO: Exception when alias already defined. @@ -130,9 +170,9 @@ class TableInfo: else: ret = datasource.get_col(parsedColExpr[1]) if self.groupinfo is not None and ret: - ret = f"{ret.k9name}[{'start' if ret in self.groupinfo.referenced else 'range'}]" + ret = f"{ret.reference()}[{'start' if ret in self.groupinfo.referenced else 'range'}]" else: - ret = ret.k9name + ret = ret.reference() return ret class View: @@ -147,17 +187,23 @@ class View: self.context.emit(f'{self.name}:()') class Context: + function_head = 'extern \"C\" int dllmain(Context* cxt){ \n' def __init__(self): self.tables:List[TableInfo] = [] self.tables_byname = dict() - self.k9cols_byname = dict() - + self.ccols_byname = dict() + self.gc_name = 'gc_' + base62uuid(4) + self.tmp_names = set() self.udf_map = dict() + self.headers = set(['\"./server/libaquery.h\"']) + self.finalized = False # read header - self.k9code = '' - self.k9codelet = '' - with open('header.k', 'r') as outfile: - self.k9code = outfile.read() + self.ccode = '' + self.ccodelet = '' + self.columns_in_context = dict() + self.tables_in_context = dict() + with open('header.cxx', 'r') as outfile: + self.ccode = outfile.read() # datasource will be availible after `from' clause is parsed # and will be deactivated when the `from' is out of scope self.datasource = None @@ -171,17 +217,28 @@ class Context: def gen_tmptable(self): from engine.utils import base62uuid return f't{base62uuid(7)}' + def reg_tmp(self, name, f): + self.tmp_names.add(name) + self.emit(f"{self.gc_name}.reg({{{name}, 0,0{'' if f is None else ',{f}'}}});") + def define_tmp(self, typename, isPtr = True, f = None): + name = 'tmp_' + base62uuid() + if isPtr: + self.emit(f'auto* {name} = new {typename};') + self.reg_tmp(name, f) + else: + self.emit(f'auto {name} = {typename};') + return name def emit(self, codelet): - self.k9code += self.k9codelet + codelet + '\n' - self.k9codelet = '' + self.ccode += self.ccodelet + codelet + '\n' + self.ccodelet = '' def emit_no_flush(self, codelet): - self.k9code += codelet + '\n' + self.ccode += codelet + '\n' def emit_flush(self): - self.k9code += self.k9codelet + '\n' - self.k9codelet = '' + self.ccode += self.ccodelet + '\n' + self.ccodelet = '' def emit_nonewline(self, codelet): - self.k9codelet += codelet + self.ccodelet += codelet def datsource_top(self): if len(self.ds_stack) > 0: @@ -200,19 +257,33 @@ class Context: return ds else: return None - + def finalize(self): + if not self.finalized: + headers = '' + for h in self.headers: + if h[0] != '"': + headers += '#include <' + h + '>\n' + else: + headers += '#include ' + h + '\n' + self.ccode = headers + self.function_head + self.ccode + 'return 0;\n}' + self.headers = set() + return self.ccode def __str__(self): - return self.k9code + self.finalize() + return self.ccode def __repr__(self) -> str: return self.__str__() class ast_node: types = dict() + header = [] def __init__(self, parent:"ast_node", node, context:Context = None): self.context = parent.context if context is None else context self.parent = parent self.datasource = None + for h in self.header: + self.context.headers.add(h) self.init(node) self.produce(node) self.spawn(node) diff --git a/engine/ddl.py b/engine/ddl.py index 2d014b3..04ddc49 100644 --- a/engine/ddl.py +++ b/engine/ddl.py @@ -7,10 +7,15 @@ class create_table(ast_node): def produce(self, node): ct = node[self.name] tbl = self.context.add_table(ct['name'], ct['columns']) - # create tables in k9 - for c in ct['columns']: - self.emit(f"{tbl.get_k9colname(c['name'])}:()") - + # create tables in c + self.emit(f"auto {tbl.table_name} = new TableInfo(\"{tbl.table_name}\", {tbl.n_cols});") + self.emit("cxt->tables.insert({\"" + tbl.table_name + f"\", {tbl.table_name}"+"});") + self.context.tables_in_context[tbl] = tbl.table_name + tbl.cxt_name = tbl.table_name + for i, c in enumerate(ct['columns']): + # TODO: more self awareness + self.emit(f"{tbl.table_name}->colrefs[{i}].ty = types::AINT;") + class insert(ast_node): name = 'insert' def produce(self, node): @@ -20,16 +25,17 @@ class insert(ast_node): values = node['query']['select'] if len(values) != table.n_cols: raise ValueError("Column Mismatch") + table.refer_all() for i, s in enumerate(values): if 'value' in s: - k9name = table.columns[i][0] - self.emit(f"{k9name}:{k9name},{s['value']}") + cname = table.columns[i].cxt_name + self.emit(f"{cname}.emplace_back({s['value']});") else: # subquery, dispatch to select astnode pass -class k9(ast_node): - name='k9' +class c(ast_node): + name='c' def produce(self, node): self.emit(node[self.name]) @@ -47,7 +53,7 @@ class load(ast_node): self.emit(f"{tablename}:({keys}!(+(`csv ? 1:\"{node['file']['literal']}\")))[{keys}]") for i, c in enumerate(table.columns): - self.emit(f'{c.k9name}:{tablename}[{i}]') + self.emit(f'{c.cname}:{tablename}[{i}]') class outfile(ast_node): name="_outfile" @@ -64,17 +70,17 @@ class outfile(ast_node): l_keys += '`' + c.name if c.compound: if l_compound: - l_cols=f'flatBOTH\'+(({ending(l_cols)});{c.k9name})' + l_cols=f'flatBOTH\'+(({ending(l_cols)});{c.cname})' else: l_compound = True if i >= 1: - l_cols = f'flatRO\'+(({ending(l_cols)});{c.k9name})' + l_cols = f'flatRO\'+(({ending(l_cols)});{c.cname})' else: - l_cols = c.k9name + ';' + l_cols = c.cname + ';' elif l_compound: - l_cols = f'flatLO\'+(({ending(l_cols)});{c.k9name})' + l_cols = f'flatLO\'+(({ending(l_cols)});{c.cname})' else: - l_cols += f"{c.k9name};" + l_cols += f"{c.cname};" if not l_compound: self.emit_no_ln(l_keys + '!(' + ending(l_cols) + ')') else: diff --git a/engine/expr.py b/engine/expr.py index 753ab47..4877377 100644 --- a/engine/expr.py +++ b/engine/expr.py @@ -54,7 +54,7 @@ class expr(ast_node): else: self.datasource = self.context.datasource self.udf_map = parent.context.udf_map - self.k9expr = '' + self.cexpr = '' self.func_maps = {**self.udf_map, **self.builtin_func_maps} def produce(self, node): @@ -63,29 +63,29 @@ class expr(ast_node): if key in self.func_maps: # if type(val) in [dict, str]: if type(val) is list and len(val) > 1: - k9func = self.func_maps[key] - k9func = k9func[len(val) - 1] if type(k9func) is list else k9func - self.k9expr += f"{k9func}[" + cfunc = self.func_maps[key] + cfunc = cfunc[len(val) - 1] if type(cfunc) is list else cfunc + self.cexpr += f"{cfunc}(" for i, p in enumerate(val): - self.k9expr += expr(self, p).k9expr + (';'if i 1: self.emit_no_ln(f"{'+' if self.inv else ''}{disp_varname}") else: - self.emit_no_ln(f'$[(#{disp_varname})>1;+,({disp_varname});+,(,{disp_varname})]') + self.emit_no_ln(f'print({disp_varname});') if flatten: self.emit_no_ln(f'{disp_varname}') if has_orderby: diff --git a/engine/scan.py b/engine/scan.py index c1e8edd..1042d6b 100644 --- a/engine/scan.py +++ b/engine/scan.py @@ -27,12 +27,12 @@ class filter(ast_node): if type(self.value) is View: # cond filtered on tables. self.emit(f'{self.value.name}:&{self.value.name}') for o, c in zip(self.output.columns,self.value.table.columns): - self.emit(f'{o.k9name}:{c.k9name}[{self.value.name}]') + self.emit(f'{o.cname}:{c.cname}[{self.value.name}]') elif self.value is not None: # cond is scalar tmpVar = 't'+base62uuid(7) self.emit(f'{tmpVar}:{self.value}') for o, c in zip(self.output.columns, self.datasource.columns): - self.emit(f'{o.k9name}:$[{tmpVar};{c.k9name};()]') + self.emit(f'{o.cname}:$[{tmpVar};{c.cname};()]') def consume(self, node): # TODO: optimizations after converting expr to cnf @@ -86,7 +86,7 @@ class filter(ast_node): elif type(v) is View: if len(v.table.columns) > 0: all_rows = View(self.context, v.table) - self.emit(f'{all_rows.name}:(#{v.table.columns[0].k9name})#1') + self.emit(f'{all_rows.name}:(#{v.table.columns[0].cname})#1') self.emit(f'{v.name}:{all_rows.name}-{v.name}') self.value = v else: @@ -97,10 +97,10 @@ class filter(ast_node): if e.isvector: v = View(self.context, self.datasource) v.construct() - self.emit(f'{v.name}:{e.k9expr}') + self.emit(f'{v.name}:{e.cexpr}') self.value = v else: - self.value = e.k9expr + self.value = e.cexpr self.__materialize__() print(node) diff --git a/engine/types.py b/engine/types.py new file mode 100644 index 0000000..3eccad0 --- /dev/null +++ b/engine/types.py @@ -0,0 +1,33 @@ +from engine.ast import Context + + +class Types: + name = 'Any' + cname = 'void*' + ctype_name = "types::NONE" + def __init__(self, context:Context): + self.cxt = context + def cast_to(self, *_): + return self + def cast_from(self, *_): + return self + def __repr__(self) -> str: + return self.cname + +class String(Types): + name = 'String' + cname = 'const char*' + ctype_name = "types::ASTR" + def cast_from(self, ty, val, container = None): + if type(ty) is Int: + self.cxt.emit() + +class Int(Types): + name = "Int" + cname = "int" + ctype_name = "types::AINT" +class Float(Types): + name = "Float" + cname = "float" + ctype_name = "types::AFLOAT" + \ No newline at end of file diff --git a/header.cxx b/header.cxx new file mode 100644 index 0000000..e69de29 diff --git a/libcsv.a b/libcsv.a new file mode 100644 index 0000000..036fac9 Binary files /dev/null and b/libcsv.a differ diff --git a/out.cpp b/out.cpp new file mode 100644 index 0000000..137e13f --- /dev/null +++ b/out.cpp @@ -0,0 +1,46 @@ +#include "./server/libaquery.h" +extern "C" int dllmain(Context* cxt){ +auto stocks = new TableInfo("stocks", 2); +cxt->tables.insert({"stocks", stocks}); +stocks->colrefs[0].ty = types::AINT; +stocks->colrefs[1].ty = types::AINT; +auto& stocks_timestamp = *(ColRef *)(&stocks->colrefs[0]); +auto& stocks_price = *(ColRef *)(&stocks->colrefs[1]); +stocks_timestamp.emplace_back(1); +stocks_price.emplace_back(15); +stocks_timestamp.emplace_back(2); +stocks_price.emplace_back(19); +stocks_timestamp.emplace_back(3); +stocks_price.emplace_back(16); +stocks_timestamp.emplace_back(4); +stocks_price.emplace_back(17); +stocks_timestamp.emplace_back(5); +stocks_price.emplace_back(15); +stocks_timestamp.emplace_back(6); +stocks_price.emplace_back(13); +stocks_timestamp.emplace_back(7); +stocks_price.emplace_back(5); +stocks_timestamp.emplace_back(8); +stocks_price.emplace_back(8); +stocks_timestamp.emplace_back(9); +stocks_price.emplace_back(7); +stocks_timestamp.emplace_back(10); +stocks_price.emplace_back(13); +stocks_timestamp.emplace_back(11); +stocks_price.emplace_back(11); +stocks_timestamp.emplace_back(12); +stocks_price.emplace_back(14); +stocks_timestamp.emplace_back(13); +stocks_price.emplace_back(10); +stocks_timestamp.emplace_back(14); +stocks_price.emplace_back(5); +stocks_timestamp.emplace_back(15); +stocks_price.emplace_back(2); +stocks_timestamp.emplace_back(16); +stocks_price.emplace_back(5); +auto d2PxTIVW = (max((stocks_price-min(stocks_timestamp)))); +print(d2PxTIVW); +auto d2dVVnjL = (max((stocks_price-mins(stocks_price)))); +print(d2dVVnjL); +return 0; +} \ No newline at end of file diff --git a/out_working.cpp b/out_working.cpp new file mode 100644 index 0000000..5fbb369 --- /dev/null +++ b/out_working.cpp @@ -0,0 +1,46 @@ +#include "./server/libaquery.h" +#include +#include +extern "C" int dllmain(Context *cxt) +{ + auto stocks = new TableInfo("stocks", 2); + cxt->tables.insert(std::make_pair("stocks", stocks)); + stocks->colrefs[0].ty = types::AINT; + stocks->colrefs[1].ty = types::AINT; + auto &stocks_0 = *(ColRef *)(&stocks->colrefs[0]); + auto &stocks_1 = *(ColRef *)(&stocks->colrefs[1]); + stocks_0.emplace_back(1); + stocks_1.emplace_back(15); + stocks_0.emplace_back(2); + stocks_1.emplace_back(19); + stocks_0.emplace_back(3); + stocks_1.emplace_back(16); + stocks_0.emplace_back(4); + stocks_1.emplace_back(17); + stocks_0.emplace_back(5); + stocks_1.emplace_back(15); + stocks_0.emplace_back(6); + stocks_1.emplace_back(13); + stocks_0.emplace_back(7); + stocks_1.emplace_back(5); + stocks_0.emplace_back(8); + stocks_1.emplace_back(8); + stocks_0.emplace_back(9); + stocks_1.emplace_back(7); + stocks_0.emplace_back(10); + stocks_1.emplace_back(13); + stocks_0.emplace_back(11); + stocks_1.emplace_back(11); + stocks_0.emplace_back(12); + stocks_1.emplace_back(14); + stocks_0.emplace_back(13); + stocks_1.emplace_back(10); + stocks_0.emplace_back(14); + stocks_1.emplace_back(5); + stocks_0.emplace_back(15); + stocks_1.emplace_back(2); + stocks_0.emplace_back(16); + stocks_1.emplace_back(5); + printf("%d\n", max(stocks_0 - min(stocks_1))); + return 0; +} \ No newline at end of file diff --git a/prompt.py b/prompt.py index 06ec96d..9e6b00c 100644 --- a/prompt.py +++ b/prompt.py @@ -1,15 +1,41 @@ import re +import time import aquery_parser as parser import engine import subprocess - +import mmap import sys +import os +from engine.utils import base62uuid +import atexit + +def rm(): + files = os.listdir('.') + for f in files: + if f.endswith('.shm'): + os.remove(f) +atexit.register(rm) + +shm = base62uuid() if sys.platform != 'win32': import readline + shm += '.shm' basecmd = ['bash', '-c', 'rlwrap k'] + mm = None + if not os.path.isfile(shm): + # create initial file + with open(shm, "w+b") as handle: + handle.write(b'\x01\x00') # [running, new job] + handle.flush() + mm = mmap.mmap(handle.fileno(), 2, access=mmap.ACCESS_WRITE, offset=0) + if mm is None: + exit(1) else: basecmd = ['bash.exe', '-c', 'rlwrap ./k'] - + mm = mmap.mmap(0, 2, shm) + mm.write(b'\x01\x00') + mm.flush() +subprocess.Popen(["./server.bin", shm]) test_parser = True # code to test parser @@ -21,6 +47,19 @@ res = parser.parse(q) print(res) + +# else:f +# if subprocess.call(['make', 'snippet']) == 0: +# mm.seek(0) +# mm.write(b'\x01\x01') +# time.sleep(.1) +# mm.seek(0) +# print(mm.read(2)) + +# mm.close() +# handle.close() +# os.remove(shm) +# exit() keep = False cxt = None while test_parser: @@ -35,10 +74,12 @@ while test_parser: engine.generate(s, cxt) else: engine.generate(stmts_stmts, cxt) - print(cxt.k9code) - with open('out.k', 'wb') as outfile: - outfile.write((cxt.k9code+'\n\\\\').encode('utf-8')) - subprocess.call(basecmd[:-1] + [basecmd[-1] + ' out.k']) + print(cxt.ccode) + with open('out.cpp', 'wb') as outfile: + outfile.write((cxt.finalize()).encode('utf-8')) + if subprocess.call(['make', 'snippet']) == 0: + mm.seek(0,os.SEEK_SET) + mm.write(b'\x01\x01') continue elif q == 'k': subprocess.call(basecmd) @@ -49,6 +90,13 @@ while test_parser: elif q == 'keep': keep = not keep continue + elif q == 'exit': + break + elif q == 'r': + if subprocess.call(['make', 'snippet']) == 0: + mm.seek(0,os.SEEK_SET) + mm.write(b'\x01\x01') + continue trimed = ws.sub(' ', q.lower()).split(' ') if trimed[0].startswith('f'): fn = 'stock.a' if len(trimed) <= 1 or len(trimed[1]) == 0 \ @@ -63,3 +111,6 @@ while test_parser: except (ValueError) as e: print(type(e), e) +mm.close() +handle.close() +os.remove(shm) \ No newline at end of file diff --git a/server/Makefile b/server/Makefile index 1ea3bba..7acb78e 100644 --- a/server/Makefile +++ b/server/Makefile @@ -1,3 +1,6 @@ debug: - g++ -g3 -O0 server/server.cpp server/table.cpp -o a.out -Wall -Wextra -Wpedantic - \ No newline at end of file + g++ -g3 -O0 server/server.cpp server/table.cpp -o a.out -Wall -Wextra -Wpedantic -lpthread + +test: + g++ --std=c++1z -g3 -O0 server.cpp table.cpp -o a.out -Wall -Wextra -Wpedantic -lpthread + diff --git a/server/gc.cpp b/server/gc.cpp new file mode 100644 index 0000000..e69de29 diff --git a/server/gc.hpp b/server/gc.hpp new file mode 100644 index 0000000..dfdccb9 --- /dev/null +++ b/server/gc.hpp @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include +#include +class GC { + template + using vector = std::vector; + template + using tuple = std::tuple; + size_t current_size, max_size, interval, forced_clean; + bool running, alive; +// ptr, dealloc, ref, sz + vector> q; + std::thread handle; + void gc() + { + + } + template + void reg(T* v, uint32_t ref, uint32_t sz, + void(*f)(void*) = [](void* v) {delete[] ((T*)v); }) { + current_size += sz; + if (current_size > max_size) + gc(); + q.push_back({ v, f, ref, sz }); + } + void daemon() { + using namespace std::chrono; + while (alive) { + if (running) { + gc(); + std::this_thread::sleep_for(microseconds(interval)); + } + else { + std::this_thread::sleep_for(10ms); + } + } + } + void start_deamon() { + handle = std::thread(&daemon); + alive = true; + } + void terminate_daemon() { + running = false; + alive = false; + using namespace std::chrono; + + if (handle.joinable()) { + std::this_thread::sleep_for(microseconds(1000 + std::max(static_cast(10000), interval))); + handle.join(); + } + } +}; \ No newline at end of file diff --git a/server/libaquery.h b/server/libaquery.h index 9674b54..9369ac9 100644 --- a/server/libaquery.h +++ b/server/libaquery.h @@ -2,8 +2,9 @@ #define _AQUERY_H #include "table.h" - -class Context{ - +#include +struct Context{ + std::unordered_map tables; + std::unordered_map cols; }; #endif \ No newline at end of file diff --git a/server/packages.config b/server/packages.config new file mode 100644 index 0000000..acb6d36 --- /dev/null +++ b/server/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/.signature.p7s b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/.signature.p7s new file mode 100644 index 0000000..25bf68b Binary files /dev/null and b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/.signature.p7s differ diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/LICENSE b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/LICENSE new file mode 100644 index 0000000..9e841e7 --- /dev/null +++ b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/Microsoft.Windows.CppWinRT.2.0.210806.1.nupkg b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/Microsoft.Windows.CppWinRT.2.0.210806.1.nupkg new file mode 100644 index 0000000..db5f291 Binary files /dev/null and b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/Microsoft.Windows.CppWinRT.2.0.210806.1.nupkg differ diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/bin/cppwinrt.exe b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/bin/cppwinrt.exe new file mode 100644 index 0000000..a78f34b Binary files /dev/null and b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/bin/cppwinrt.exe differ diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/CppWinrtRules.Project.xml b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/CppWinrtRules.Project.xml new file mode 100644 index 0000000..bd0efd5 --- /dev/null +++ b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/CppWinrtRules.Project.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/Microsoft.Windows.CppWinRT.props b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/Microsoft.Windows.CppWinRT.props new file mode 100644 index 0000000..d7e2c65 --- /dev/null +++ b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/Microsoft.Windows.CppWinRT.props @@ -0,0 +1,66 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + x64 + true + true + false + CppWinRT + true + + true + + PreventSdkUapPropsAssignment + true + + + + + false + stdcpp17 + + + true + $(IntDir)Unmerged\%(Filename).winmd + None + None + false + false + nul + nul + nul + nul + + + + + false + + + + false + + + + + + + + + diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/Microsoft.Windows.CppWinRT.targets b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/Microsoft.Windows.CppWinRT.targets new file mode 100644 index 0000000..16d0b02 --- /dev/null +++ b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/Microsoft.Windows.CppWinRT.targets @@ -0,0 +1,888 @@ + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + normal + -verbose + $(OutDir)$(RootNamespace).winmd + $(IntDir)Merged\ + $(IntDir)Unmerged\ + true + false + true + false + true + false + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)))..\..\ + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory))) + $(CppWinRTParameters) -fastabi + "$(CppWinRTPackageDir)bin\" + "$(CppWinRTPackageDir)" + + + true + C++ + Windows.UI.Xaml + $(GeneratedFilesDir)XamlMetaDataProvider.idl + $(GeneratedFilesDir)XamlMetaDataProvider.cpp + + $(IntDir)$(MSBuildProjectFile).mdmerge.rsp + $(IntDir)$(MSBuildProjectFile).midlrt.rsp + $(IntDir)$(MSBuildProjectFile).cppwinrt_plat.rsp + $(IntDir)$(MSBuildProjectFile).cppwinrt_ref.rsp + $(IntDir)$(MSBuildProjectFile).cppwinrt_comp.rsp + + + + false + + false + true + true + true + + $(IntDir)Generated Files\ + + $(GeneratedFilesDir) + + $(WindowsSDK_MetadataPathVersioned) + + $(GeneratedFilesDir);$(CAExcludePath) + + + $(PrepareForBuildDependsOn); + CppWinRTVerifyKitVersion; + + + + $(BeforeMidlCompileTargets);CppWinRTAddXamlMetaDataProviderIdl; + + + $(ComputeMidlInputsTargets);CppWinRTComputeXamlGeneratedMidlInputs;CppWinRTSetMidlReferences; + + + $(AfterMidlTargets); + GetCppWinRTMdMergeInputs; + CppWinRTMergeProjectWinMDInputs; + CppWinRTGetResolvedWinMD; + CppWinRTCopyWinMDToOutputDirectory; + + + $(ResolveReferencesDependsOn); + CppWinRTImplicitlyExpandTargetPlatform + + + $(ResolveAssemblyReferencesDependsOn);GetCppWinRTProjectWinMDReferences;CppWinRTMarkStaticLibrariesPrivate; + + + + $(BeforeClCompileTargets);CppWinRTAddXamlMetaDataProviderCpp;CppWinRTMakeProjections; + + + + + CppWinRTComputeXamlGeneratedCompileInputs;$(ComputeCompileInputsTargets);CppWinRTHeapEnforcementOptOut; + + + + $(MarkupCompilePass1DependsOn);CppWinRTAddXamlReferences + + + $(MarkupCompilePass2DependsOn);CppWinRTSetXamlLocalAssembly + + + $(CleanDependsOn);CppWinRTClean + + + $(GetTargetPathDependsOn);CppWinRTGetResolvedWinMD + + + $(GetPackagingOutputsDependsOn);CppWinRTGetResolvedWinMD + + + + + + + false + + + + + <_CppWinRT_RS4OrGreater>false + <_CppWinRT_RS4OrGreater Condition="'$(TargetPlatformVersion)' >= '10.0.17134.0'">true + + + + + + + <_FilesToDelete Remove="@(_FilesToDelete)"/> + <_FilesToDelete Include="$(GeneratedFilesDir)**"/> + <_FilesToDelete Include="$(CppWinRTMergedDir)**"/> + <_FilesToDelete Include="$(CppWinRTUnmergedDir)**"/> + <_FilesToDelete Include="$(CppWinRTProjectWinMD)"/> + + + + + + + + %(ClCompile.AdditionalOptions) /DWINRT_NO_MAKE_DETECTION + + + + + + + + + <_TargetPlatformWinMDs Condition="'$(TargetPlatformSdkRootOverride)' != ''" Include="$(TargetPlatformSdkRootOverride)\References\$(XeWin10TargetVersion)\**\*.winmd"> + true + false + $(TargetPlatformMoniker) + $(TargetPlatformDisplayName) + CppWinRTImplicitlyExpandTargetPlatform + True + + <_TargetPlatformWinMDs Condition="'$(TargetPlatformSdkRootOverride)' == ''" Include="$(WindowsSDK_MetadataPathVersioned)\**\*.winmd"> + true + false + $(TargetPlatformMoniker) + $(TargetPlatformDisplayName) + CppWinRTImplicitlyExpandTargetPlatform + True + + + + + + + + + + <_ResolveAssemblyReferenceResolvedFiles Include="@(_TargetPlatformWinMDs)" /> + + + <_TargetPlatformWinMDs Remove="@(_TargetPlatformWinMDs)" /> + + + + + + + + + true + true + + + false + + + + + + + + + + + + + + + + + <_CppWinRTProjectWinMDItems Include="$(CppWinRTProjectWinMD)" /> + + + $([System.IO.Path]::GetFileName('$(CppWinRTProjectWinMD)')) + true + $(WinMDImplementationPath)$(TargetName)$(TargetExt) + winmd + true + $(MSBuildProjectName) + $(ConfigurationType) + + + <_CppWinRTProjectWinMDItems Remove="$(CppWinRTProjectWinMD)" /> + + + + + + + + + <_ResolvedProjectReferencePaths Condition="'%(_ResolvedProjectReferencePaths.ProjectType)' == 'StaticLibrary'"> + false + + + + + + + + <_CppWinRTPlatformWinMDInputs Remove="@(_CppWinRTPlatformWinMDInputs)" /> + <_CppWinRTPlatformWinMDInputs Include="@(CppWinRTPlatformWinMDReferences)" /> + + %(FullPath) + + + + + + + + + <_CppWinRTPlatformWinMDReferences Remove="@(_CppWinRTPlatformWinMDReferences)" /> + <_CppWinRTPlatformWinMDReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.IsSystemReference)' == 'true' and '%(ReferencePath.WinMDFile)' == 'true' and '%(ReferencePath.ReferenceSourceTarget)' == 'ResolveAssemblyReference'" /> + + <_CppWinRTPlatformWinMDReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.IsSystemReference)' == 'true' and '%(ReferencePath.WinMDFile)' == 'true' and '%(ReferencePath.ResolvedFrom)' == 'ImplicitlyExpandTargetPlatform'" /> + + <_CppWinRTPlatformWinMDReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.IsSystemReference)' == 'true' and '%(ReferencePath.WinMDFile)' == 'true' and '%(ReferencePath.ResolvedFrom)' == 'CppWinRTImplicitlyExpandTargetPlatform'" /> + <_CppWinRTPlatformWinMDReferences Include="$(CppWinRTSDKReferences)" /> + + + %(FullPath) + + + + + + + + + <_CppWinRTDirectWinMDReferences Remove="@(_CppWinRTDirectWinMDReferences)" /> + <_CppWinRTDirectWinMDReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.IsSystemReference)' != 'true' and '%(ReferencePath.WinMDFile)' == 'true' and '%(ReferencePath.ReferenceSourceTarget)' == 'ResolveAssemblyReference'" /> + <_CppWinRTDirectWinMDReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.WinMDFile)' == 'true' and '%(ReferencePath.ReferenceSourceTarget)' == 'ExpandSDKReference'" /> + + + %(FullPath) + + + + + + + + + + <_CppWinRTStaticProjectReferences Remove="@(_CppWinRTStaticProjectReferences)"/> + <_CppWinRTStaticProjectReferences Include="@(_ResolvedProjectReferencePaths)" + Condition= "'%(_ResolvedProjectReferencePaths.ProjectType)'=='StaticLibrary' AND + '%(_ResolvedProjectReferencePaths.WinMDFile)' == 'true'"/> + + <_CppWinRTDynamicProjectReferences Remove="@(_CppWinRTDynamicProjectReferences)"/> + <_CppWinRTDynamicProjectReferences Include="@(_ResolvedProjectReferencePaths)" + Condition= "'%(_ResolvedProjectReferencePaths.ProjectType)'!='StaticLibrary' AND + ('%(_ResolvedProjectReferencePaths.WinMDFile)' == 'true' OR + ('%(_ResolvedProjectReferencePaths.WinMDFile)' == '' AND '%(_ResolvedProjectReferencePaths.Extension)' == '.winmd'))"/> + + + + + %(FullPath) + + + + %(FullPath) + + + + + + + + + + + + <_MdMergeInputs Remove="@(_MdMergeInputs)"/> + <_MdMergeInputs Include="@(Midl)"> + %(Midl.OutputDirectory)%(Midl.MetadataFileName) + $(CppWinRTProjectWinMD) + + + <_MdMergeInputs Include="@(CppWinRTStaticProjectWinMDReferences)" Condition="'$(ConfigurationType)' != 'StaticLibrary'"> + $(CppWinRTProjectWinMD) + + <_MdMergeReferences Remove="@(_MdMergeReferences)" /> + + <_MdMergeReferences Include="@(CppWinRTStaticProjectWinMDReferences)" Condition="'$(ConfigurationType)' == 'StaticLibrary'" /> + <_MdMergeReferences Include="@(CppWinRTDirectWinMDReferences)" /> + <_MdMergeReferences Include="@(CppWinRTDynamicProjectWinMDReferences)" /> + <_MdMergeReferences Include="@(CppWinRTPlatformWinMDReferences)" /> + + + + + + + + + + + + + + <_DisableReferences>false + <_DisableReferences Condition="('$(CppWinRTOverrideSDKReferences)' != 'true') and ('$(TargetPlatformVersion)' < '10.0.18310.0')">true + + + + + + >true + + + + + + + + + + + XamlGenerated + + + + + + + + <_DisableReferences>false + <_DisableReferences Condition="('$(CppWinRTOverrideSDKReferences)' != 'true') and ('$(TargetPlatformVersion)' < '10.0.18310.0')">true + [$(XamlNamespace).Markup.FullXamlMetadataProvider] + import "$(XamlNamespace).Markup.idl"%3b + +// This file is generated by the build to support Xaml apps +$(XamlMarkupIdlImport) +namespace $(RootNamespace) +{ + $(FullXamlMetadataProviderAttribute)runtimeclass XamlMetaDataProvider : [default] $(XamlNamespace).Markup.IXamlMetadataProvider + { + XamlMetaDataProvider()%3b + } +} + + + + + + + + + + <_PCH>@(ClCompile->Metadata('PrecompiledHeaderFile')->Distinct()) + #include "$(_PCH)" + +// This file is generated by the build to support Xaml apps +$(XamlMetaDataProviderPch) +#include "XamlMetaDataProvider.h" +#include "XamlMetaDataProvider.g.cpp" + + + + + + + + + + <_MidlReferences Remove="@(_MidlReferences)"/> + <_MidlReferences Include="@(CppWinRTDirectWinMDReferences)"/> + <_MidlReferences Include="@(CppWinRTStaticProjectWinMDReferences)"/> + <_MidlReferences Include="@(CppWinRTDynamicProjectWinMDReferences)"/> + <_MidlReferences Include="@(CppWinRTPlatformWinMDReferences)"/> + <_MidlReferencesDistinct Remove="@(_MidlReferencesDistinct)" /> + <_MidlReferencesDistinct Include="@(_MidlReferences->'%(WinMDPath)'->Distinct())" /> + + %(Midl.AdditionalOptions) %40"$(CppWinRTMidlResponseFile)" + + + + <_MidlrtParameters>@(_MidlReferencesDistinct->'/reference "%(WinMDPath)"',' ') + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_MdMergeDepth Condition="'$(CppWinRTNamespaceMergeDepth)' != ''">-n:$(CppWinRTNamespaceMergeDepth) + <_MdMergeDepth Condition="'$(_MdMergeDepth)' == ''">$(CppWinRTMergeDepth) + <_MdMergeDepth Condition="'$(_MdMergeDepth)' == '' And '$(CppWinRTRootNamespaceAutoMerge)' == 'true'">-n:$(RootNamespace.Split('.').length) + <_MdMergeDepth Condition="'$(_MdMergeDepth)' == '' And ('@(Page)' != '' Or '@(ApplicationDefinition)' != '')">-n:1 + <_MdMergeCommand>$(MdMergePath)mdmerge %40"$(CppWinRTMdMergeResponseFile)" + + + + <_MdMergeParameters Condition="'$(CppWinRTMergeNoValidate)'!='true'">-v + <_MdMergeParameters>$(_MdMergeParameters) @(CppWinRTMdMergeMetadataDirectories->'-metadata_dir "%(RelativeDir)."', ' ') + <_MdMergeParameters>$(_MdMergeParameters) @(CppWinRTMdMergeInputs->'-i "%(Identity)"', ' ') + <_MdMergeParameters>$(_MdMergeParameters) -o "$(CppWinRTMergedDir.TrimEnd('\'))" -partial $(_MdMergeDepth) + + + + + + + + + + + <_MdMergedOutput Remove="@(_MdMergedOutput)"/> + <_MdMergedOutput Include="$(CppWinRTMergedDir)*.winmd"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(CppWinRTPath)cppwinrt %40"$(CppWinRTPlatformProjectionResponseFile)" + + + <_CppwinrtInputs Remove="@(_CppwinrtInputs)"/> + <_CppwinrtInputs Include="@(CppWinRTPlatformWinMDInputs)"/> + + + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtInputs->'-in "%(WinMDPath)"', ' ') + <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(CppWinRTPath)cppwinrt %40"$(CppWinRTReferenceProjectionResponseFile)" + + + <_CppwinrtRefInputs Remove="@(_CppwinrtRefInputs)"/> + <_CppwinrtRefInputs Include="@(CppWinRTDirectWinMDReferences)"/> + <_CppwinrtRefInputs Include="@(CppWinRTDynamicProjectWinMDReferences)"/> + <_CppwinrtRefRefs Remove="@(_CppwinrtRefRefs)"/> + <_CppwinrtRefRefs Include="@(CppWinRTPlatformWinMDReferences)"/> + + + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefInputs->'-in "%(WinMDPath)"', ' ') + <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefRefs->'-ref "%(WinMDPath)"', ' ') + <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_PCH>@(ClCompile->Metadata('PrecompiledHeaderFile')->Distinct()) + + + + true + $(_PCH) + + + -prefix + -pch $(CppWinRTPrecompiledHeader) + $(CppWinRTPath)cppwinrt %40"$(CppWinRTComponentProjectionResponseFile)" + + + + <_MdMergedOutput Remove="@(_MdMergedOutput)"/> + <_MdMergedOutput Include="$(CppWinRTMergedDir)*.winmd"/> + <_CppwinrtCompInputs Remove="@(_CppwinrtCompInputs)"/> + <_CppwinrtCompInputs Include="@(_MdMergedOutput)"> + %(_MdMergedOutput.FullPath) + + + <_CppwinrtCompInputs Include="@(CppWinRTStaticProjectWinMDReferences)" Condition="'$(ConfigurationType)' == 'StaticLibrary'"> + %(CppWinRTStaticProjectWinMDReferences.FullPath) + + <_CppwinrtCompRefs Remove="@(_CppwinrtCompRefs)"/> + <_CppwinrtCompRefs Include="@(CppWinRTDirectWinMDReferences)"/> + <_CppwinrtCompRefs Include="@(CppWinRTDynamicProjectWinMDReferences)"/> + <_CppwinrtCompRefs Include="@(CppWinRTPlatformWinMDReferences)"/> + + + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" + <_CppwinrtParameters Condition="'$(CppWinRTOptimized)'=='true'">$(_CppwinrtParameters) -opt + <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompInputs->'-in "%(WinMDPath)"', ' ') + <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompRefs->'-ref "%(WinMDPath)"', ' ') + <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." + + + + + + + + + + + + + + + + + + + + + + + + + + $(CppWinRTProjectWinMD) + + + + + + + %(AdditionalOptions) /bigobj + %(AdditionalOptions) /await + %(AdditionalIncludeDirectories);$(GeneratedFilesDir) + + + $(WindowsSDK_MetadataFoundationPath);%(AdditionalMetadataDirectories) + $(WindowsSDK_MetadataPath);%(AdditionalMetadataDirectories) + %(AdditionalOptions) /nomidl + + + %(AdditionalDependencies);WindowsApp.lib + %(AdditionalDependencies);$(CppWinRTPackageDir)build\native\lib\$(Platform)\cppwinrt_fast_forwarder.lib + + + + diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/arm/cppwinrt_fast_forwarder.lib b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/arm/cppwinrt_fast_forwarder.lib new file mode 100644 index 0000000..18e1845 Binary files /dev/null and b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/arm/cppwinrt_fast_forwarder.lib differ diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/arm64/cppwinrt_fast_forwarder.lib b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/arm64/cppwinrt_fast_forwarder.lib new file mode 100644 index 0000000..2203db5 Binary files /dev/null and b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/arm64/cppwinrt_fast_forwarder.lib differ diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/win32/cppwinrt_fast_forwarder.lib b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/win32/cppwinrt_fast_forwarder.lib new file mode 100644 index 0000000..6788f38 Binary files /dev/null and b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/build/native/lib/win32/cppwinrt_fast_forwarder.lib differ diff --git a/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/readme.txt b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/readme.txt new file mode 100644 index 0000000..049ab13 --- /dev/null +++ b/server/packages/Microsoft.Windows.CppWinRT.2.0.210806.1/readme.txt @@ -0,0 +1,22 @@ +======================================================================== +The Microsoft.Windows.CppWinRT NuGet package automatically generates C++/WinRT projection headers, +enabling you to both consume and produce Windows Runtime classes. +======================================================================== + +C++/WinRT detects Windows metadata required by the project, from: +* Platform winmd files in the SDK (both MSI and NuGet) +* NuGet package references containing winmd files +* Other project references producing winmd files +* Raw winmd file references +* Interface definition language (IDL) files in the project + +For any winmd file discovered above, C++/WinRT creates reference (consuming) projection headers. +Client code can simply #include these headers, which are created in the generated files directory (see below). + +For any IDL file contained in the project, C++/WinRT creates component (producing) projection headers. +In addition, C++/WinRT generates templates and skeleton implementations for each runtime class, under the Generated Files directory. + +======================================================================== +For more information, visit: +https://github.com/Microsoft/cppwinrt/tree/master/nuget +======================================================================== diff --git a/server/server.cpp b/server/server.cpp index a373a37..4ff2501 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -1,17 +1,94 @@ +#include "../csv.h" #include +#include +//#include +#include #include "libaquery.h" #ifdef _WIN32 #include "winhelper.h" #else #include +#include +#include +struct SharedMemory +{ + int hFileMap; + void* pData; + SharedMemory(const char* fname) { + hFileMap = open(fname, O_RDWR, 0); + if (hFileMap != -1) + pData = mmap(NULL, 8, PROT_READ | PROT_WRITE, MAP_SHARED, hFileMap, 0); + else + pData = 0; + } + void FreeMemoryMap() { + + } +}; #endif +struct thread_context{ + +}v; +void daemon(thread_context* c) { + +} typedef int (*code_snippet)(void*); -int main() +int _main(); +int main(int argc, char** argv) { + printf("%d %s\n", argc, argv[1]); + const char* shmname; + if (argc <= 1) + return _main(); + else + shmname = argv[1]; + SharedMemory shm = SharedMemory(shmname); + if (!shm.pData) + return 1; + bool &running = static_cast(shm.pData)[0], + &ready = static_cast(shm.pData)[1]; + Context *cxt = new Context(); + using namespace std::chrono_literals; + printf("running: %s\n", running? "true":"false"); + printf("ready: %s\n", ready? "true":"false"); + while (running) { + std::this_thread::sleep_for(1us); + if(ready){ + printf("running: %s\n", running? "true":"false"); + printf("ready: %s\n", ready? "true":"false"); + void* handle = dlopen("./dll.so", RTLD_LAZY); + printf("handle: %x\n", handle); + if (handle) { + printf("inner\n"); + code_snippet c = reinterpret_cast(dlsym(handle, "dllmain")); + printf("routine: %x\n", c); + if (c) { + printf("inner\n"); + printf("return: %d\n", c(cxt)); + } + dlclose(handle); + } + ready = false; + } + } + shm.FreeMemoryMap(); + return 0; +} +int _main() { + using string = std::string; + using std::cout; + using std::thread; void* handle = dlopen("dll.so", RTLD_LAZY); - code_snippet c = static_cast(dlsym(handle, "dlmain")); - printf("%d", c(0)); - dlclose(handle); + io::CSVReader<4> in("../test.csv"); + in.read_header(io::ignore_extra_column, "a", "b", "c", "d"); + int a, b, cc, d; + string tp, tpdf, st; + while (in.read_row(a, b, cc, d)) + cout << a<< ' ' << b <<' ' << cc <<' ' << d << '\n'; + + //code_snippet c = reinterpret_cast(dlsym(handle, "dlmain")); + //printf("%d", c(0)); + //dlclose(handle); vector_type t1{ 1.2, 3.4, .2, 1e-5, 1, 3, 5, 4, 5}; vector_type t2{ 2, 4, 3, 5, 0, 2, 6, 1, 2}; printf("x: "); @@ -20,6 +97,50 @@ int main() printf("%lf ", x); } puts(""); + + Context* cxt = new Context(); + auto stocks = TableInfo("stocks", 2); + cxt->tables.insert(std::make_pair("stocks", &stocks)); + + auto& stocks_0 = get<0>(stocks); + auto& stocks_1 = get<1>(stocks); + + stocks_0.init(); + stocks_1.init(); + + stocks_0.emplace_back(1); + stocks_1.emplace_back(15); + stocks_0.emplace_back(2); + stocks_1.emplace_back(19); + stocks_0.emplace_back(3); + stocks_1.emplace_back(16); + stocks_0.emplace_back(4); + stocks_1.emplace_back(17); + stocks_0.emplace_back(5); + stocks_1.emplace_back(15); + stocks_0.emplace_back(6); + stocks_1.emplace_back(13); + stocks_0.emplace_back(7); + stocks_1.emplace_back(5); + stocks_0.emplace_back(8); + stocks_1.emplace_back(8); + stocks_0.emplace_back(9); + stocks_1.emplace_back(7); + stocks_0.emplace_back(10); + stocks_1.emplace_back(13); + stocks_0.emplace_back(11); + stocks_1.emplace_back(11); + stocks_0.emplace_back(12); + stocks_1.emplace_back(14); + stocks_0.emplace_back(13); + stocks_1.emplace_back(10); + stocks_0.emplace_back(14); + stocks_1.emplace_back(5); + stocks_0.emplace_back(15); + stocks_1.emplace_back(2); + stocks_0.emplace_back(16); + stocks_1.emplace_back(5); + printf("%d\n", max(stocks_0 - mins(stocks_1))); return 0; } diff --git a/server/server.vcxproj b/server/server.vcxproj index bf25b39..92ea8c3 100644 --- a/server/server.vcxproj +++ b/server/server.vcxproj @@ -1,5 +1,6 @@ - + + Debug @@ -86,8 +87,9 @@ Level3 true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 Console @@ -100,8 +102,9 @@ true true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 Console @@ -114,8 +117,9 @@ Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 Console @@ -128,8 +132,9 @@ true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 Console @@ -141,20 +146,33 @@ + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/server/table.h b/server/table.h index 78626ec..5e8fd88 100644 --- a/server/table.h +++ b/server/table.h @@ -4,28 +4,164 @@ #include "types.h" #include "vector_type.hpp" -template +template class vector_type; +template <> +class vector_type; #ifdef _MSC_VER namespace types { enum Type_t; + template + struct Types; + template + struct Coercion; } #endif -template -class ColRef : public vector_type +template +class ColRef : public vector_type<_Ty> { +public: const char* name; - types::Type_t ty; + types::Type_t ty = types::ERROR; + ColRef(uint32_t size, const char* name = "") : vector_type<_Ty>(size), name(name) {} ColRef(const char* name) : name(name) {} + void init() { ty = types::Types<_Ty>::getType(); this->size = this->capacity = 0; this->container = 0; } + ColRef(const char* name, types::Type_t ty) : name(name), ty(ty) {} + + template + ColRef scast(); }; -class TableInfo { +template +template +inline ColRef ColRef<_Ty>::scast() +{ + this->ty = types::Types::getType(); + return *(ColRef *)this; +} +using uColRef = ColRef; +template +struct TableInfo { const char* name; ColRef* colrefs; - uint32_t n_cols; + uint32_t n_cols, n_rows; + //void print(); + TableInfo(const char* name, uint32_t n_cols); }; +template +constexpr static inline bool is_vector(const ColRef&) { + return true; +} +template +constexpr static inline bool is_vector(const vector_type&) { + return true; +} +template +constexpr static inline bool is_vector(const T&) { + return false; +} +template +TableInfo::TableInfo(const char* name, uint32_t n_cols) : name(name), n_cols(n_cols) { + this->colrefs = (ColRef*)malloc(sizeof(ColRef) * n_cols); +} + +template +ColRef::type> operator -(const ColRef& lhs, const ColRef& rhs) { + auto ret = ColRef::type>(lhs.size, ""); + for (int i = 0; i < lhs.size; ++i) + ret.container[i] = lhs.container[i] - rhs.container[i]; + return ret; +} +template +ColRef::type> operator -(const ColRef& lhs, const T2& rhs) { + auto ret = ColRef::type>(lhs.size, ""); + for (int i = 0; i < lhs.size; ++i) + ret.container[i] = lhs.container[i] - rhs; + return ret; +} + +template +constexpr ColRef>>& get(TableInfo<_Types...>& table) noexcept { + return *(ColRef< std::tuple_element_t<_Index, std::tuple<_Types...>>> *) &(table.colrefs[_Index]); +} + + +//void TableInfo::print() +//{ +// for (int i = 0; i < n_rows; ++i) { +// for (int j = 0; j < n_cols; ++j) // TODO: Deal with date/time +// printf(types::printf_str[colrefs[j].ty], colrefs[j].get(i, colrefs[j].ty)); +// puts(""); +// } +//} +template +ColRef mins(const ColRef& arr) { + const int& len = arr.size; + std::deque> cache; + ColRef ret(len); + T min = std::numeric_limits::max(); + for (int i = 0; i < len; ++i) { + if (arr[i] < min) + min = arr[i]; + ret[i] = min; + } + return ret; +} +template +ColRef maxs(const ColRef& arr) { + const int& len = arr.size; + ColRef ret(len); + T max = std::numeric_limits::min(); + for (int i = 0; i < len; ++i) { + if (arr[i] > max) + max = arr[i]; + ret[i] = max; + } + return ret; +} + +template +ColRef minw(const ColRef& arr, uint32_t w) { + const int& len = arr.size; + ColRef ret(len); + std::deque> cache; + for (int i = 0; i < len; ++i) { + if (!cache.empty() && cache.front().second == i - w) cache.pop_front(); + while (!cache.empty() && cache.back().first > arr[i]) cache.pop_back(); + cache.push_back({ arr[i], i }); + ret[i] = cache.front().first; + } + return ret; +} +template +ColRef maxw(const ColRef& arr, uint32_t w) { + const int& len = arr.size; + ColRef ret(len); + std::deque> cache; + for (int i = 0; i < len; ++i) { + if (!cache.empty() && cache.front().second == i - w) cache.pop_front(); + while (!cache.empty() && cache.back().first > arr[i]) cache.pop_back(); + cache.push_back({ arr[i], i }); + arr[i] = cache.front().first; + } + return ret; +} + +template +void print(const T& v) { + printf(types::printf_str[types::Types::getType()], v); +} + +template +void print(const ColRef& v, const char* delimiter) { + + for (const auto& vi : v) { + print(vi); + puts(delimiter); + } +} #endif \ No newline at end of file diff --git a/server/types.cpp b/server/types.cpp new file mode 100644 index 0000000..9a344c2 --- /dev/null +++ b/server/types.cpp @@ -0,0 +1,25 @@ +#include "types.h" +#include +#include +//template +//inline static constexpr void types::Types::print(T& v) +//{ +// std::cout << v; +//} +#include +#include +namespace types { + using namespace std; + using namespace chrono; + string date_t::toString() const { + uint32_t curr_v = val; + tm; + time_t; + return string() + string("/") + string() + string("/") + string(); + } + string time_t::toString() const { + uint32_t curr_v = val; + + return string() + string("/") + string() + string("/") + string(); + } +} \ No newline at end of file diff --git a/server/types.h b/server/types.h index 1636651..b4ed73c 100644 --- a/server/types.h +++ b/server/types.h @@ -4,38 +4,37 @@ #include #include #include -#include "table.h" - +#include +#ifdef _MSC_VER +#define __restrict__ __restrict +#endif namespace types { enum Type_t { - AINT, AFLOAT, ASTR, ADOUBLE, ALDOUBLE, ALONG, ASHORT, ADATE, ATIME, ACHAR, NONE, - AUINT, AULONG, AUSHORT, AUCHAR + AINT, AFLOAT, ASTR, ADOUBLE, ALDOUBLE, ALONG, ASHORT, ADATE, ATIME, ACHAR, + AUINT, AULONG, AUSHORT, AUCHAR, NONE, ERROR }; - + static constexpr const char* printf_str[] = { "%d ", "%f ", "%s ", "%lf ", "%llf ", "%ld ", "%hi ", "%s ", "%s ", "%c ", + "%u ", "%lu ", "%hu ", "%hhu ", "NULL " }; // TODO: deal with data/time <=> str/uint conversion struct date_t { uint32_t val; date_t(const char* d) { } - const char* toString() const{ - return ""; - } + std::string toString() const; }; struct time_t { uint32_t val; time_t(const char* d) { } - const char* toString() const { - return ""; - } + std::string toString() const; }; template struct Types { typedef T type; constexpr Types() noexcept = default; -#define ConnectTypes(f, x, y) \ +#define ConnectTypes(f) \ f(int, AINT) \ f(float, AFLOAT) \ f(const char*, ASTR) \ @@ -45,18 +44,21 @@ namespace types { f(short, ASHORT) \ f(date_t, ADATE) \ f(time_t, ATIME) \ - f(unsigned short, AUSHORT) \ - f(unsigned long, AULONG) \ - f(unsigned int, AUINT) \ f(unsigned char, ACHAR) \ - f(void, NONE) + f(unsigned int, AUINT) \ + f(unsigned long, AULONG) \ + f(unsigned short, AUSHORT) \ + f(unsigned char, AUCHAR) - constexpr Type_t getType() const { + constexpr static Type_t getType() { #define TypeConnect(x, y) if(typeid(T) == typeid(x)) return y; else - ConnectTypes(TypeConnect, x, y) - return NONE; + ConnectTypes(TypeConnect) + return NONE; } + //static constexpr inline void print(T& v); }; +#define ATypeSize(t, at) sizeof(t), + static constexpr size_t AType_sizes[] = { ConnectTypes(ATypeSize) 1 }; #define Cond(c, x, y) typename std::conditional::type #define Comp(o) (sizeof(T1) o sizeof(T2)) #define Same(x, y) (std::is_same_v) @@ -64,9 +66,19 @@ namespace types { #define Fp(x) std::is_floating_point::value template struct Coercion { - using t1 = Cond(Comp(<=), Cond(Comp(==), Cond(Fp(T1), T1, Cond(Fp(T2), T2, Cond(_U(T1), T2, T1))), T2), T1); + using t1 = Cond(Comp(<= ), Cond(Comp(== ), Cond(Fp(T1), T1, Cond(Fp(T2), T2, Cond(_U(T1), T2, T1))), T2), T1); using t2 = Cond(Same(T1, T2), T1, Cond(Same(T1, const char*) || Same(T2, const char*), const char*, void)); using type = Cond(Same(t2, void), Cond(Same(T1, date_t) && Same(T2, time_t) || Same(T1, time_t) && Same(T2, time_t), void, t1), t2); }; +#define __Eq(x) (sizeof(T) == sizeof(x)) + template + struct GetFPType { + using type = Cond(__Eq(float), float, Cond(__Eq(double), double, long double)); + }; + template + struct GetLongType + { + using type = Cond(_U(T), unsigned long long, Cond(Fp(T), long double, long long)); + }; } #endif // !_TYPES_H diff --git a/server/utils.h b/server/utils.h new file mode 100644 index 0000000..8a53238 --- /dev/null +++ b/server/utils.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include +using std::string; +string base62uuid(int l = 8) { + constexpr static const char* base62alp = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static mt19937_64 engine(chrono::system_clock::now().time_since_epoch().count()); + static uniform_int_distribution u(0x100000000, 0xfffffffff); + uint64_t uuid = (u(engine)<<16ull) + (time(0)&0xffff); + printf("%lx\n", uuid); + string ret; + while (uuid && l-- >= 0){ + ret = string("") + base62alp[uuid % 62] + ret; + uuid /= 62; + } + return ret; +} \ No newline at end of file diff --git a/server/vector_type.cpp b/server/vector_type.cpp index 4ab58c3..adca79c 100644 --- a/server/vector_type.cpp +++ b/server/vector_type.cpp @@ -1 +1 @@ -#include "vector_type.hpp" \ No newline at end of file +#include "vector_type.hpp" diff --git a/server/vector_type.hpp b/server/vector_type.hpp index 9251c7b..a307c4e 100644 --- a/server/vector_type.hpp +++ b/server/vector_type.hpp @@ -14,7 +14,8 @@ #include #include #include - +#include +#include #include "types.h" #pragma pack(push, 1) @@ -45,12 +46,12 @@ public: } constexpr vector_type(std::initializer_list<_Ty> _l) { size = capacity = _l.size(); - _Ty* container = this->container = (_Ty*)malloc(sizeof(_Ty) * _l.size()); + _Ty* _container = this->container = (_Ty*)malloc(sizeof(_Ty) * _l.size()); for (const auto& l : _l) { - *(container++) = l; + *(_container++) = l; } } - constexpr vector_type() noexcept = default; + constexpr vector_type() noexcept {}; constexpr vector_type(vector_type<_Ty>& vt) noexcept { _copy(vt); } @@ -67,7 +68,7 @@ public: } void emplace_back(_Ty _val) { if (size >= capacity) { // geometric growth - capacity += 1 + capacity >> 1; + capacity += 1 + (capacity >> 1); _Ty* n_container = (_Ty*)malloc(capacity * sizeof(_Ty)); memcpy(n_container, container, sizeof(_Ty) * size); free(container); @@ -216,5 +217,65 @@ public: _Make_Ops(Ops) _Make_Ops(Opseq) }; + + +template <> +class vector_type { +public: + void* container; + uint32_t size, capacity; + typedef void* iterator_t; + + vector_type(uint32_t size) : size(size), capacity(size) { + container = (void*)malloc(size); + } + template + constexpr vector_type(std::initializer_list<_Ty> _l) { + size = capacity = _l.size(); + this->container = malloc(sizeof(_Ty) * _l.size()); + _Ty* _container = (_Ty*)this->container; + for (const auto& l : _l) { + *(_container++) = l; + } + } + constexpr vector_type() : size(0), capacity(0), container(0) {}; + void *get(uint32_t i, types::Type_t atype){ + + return static_cast(static_cast(container) + (i * types::AType_sizes[atype])); + } +}; #pragma pack(pop) + + + + +// TODO: Specializations for dt/str/none +template +types::GetLongType sum(const vector_type &v) { + types::GetLongType ret = 0; + for (const auto& _v : v) + ret += _v; + return ret; +} +template +types::GetFPType avg(const vector_type &v) { + return static_cast>( + sum(v)/static_cast(v.size)); +} +template +T max(const vector_type& v) { + T max_v = std::numeric_limits::min(); + for (const auto& _v : v) + max_v = max_v > _v ? max_v : _v; + return max_v; +} +template +T min(const vector_type& v) { + T min_v = std::numeric_limits::max(); + for (const auto& _v : v) + min_v = min_v < _v ? min_v : _v; + return min_v; +} + + #endif diff --git a/server/winhelper.cpp b/server/winhelper.cpp index 94d722a..1ed27c7 100644 --- a/server/winhelper.cpp +++ b/server/winhelper.cpp @@ -16,3 +16,21 @@ int dlclose(void* handle) { return FreeLibrary(static_cast(handle)); } + +SharedMemory::SharedMemory(const char* fname) +{ + this->hFileMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 2, fname); + if (this->hFileMap) + this->pData = MapViewOfFile(this->hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 2); + else + this->pData = NULL; +} + +void SharedMemory::FreeMemoryMap() +{ + if (this->hFileMap) + if (this->pData) + UnmapViewOfFile(this->pData); + if (this->hFileMap) + CloseHandle(this->hFileMap); +} \ No newline at end of file diff --git a/server/winhelper.h b/server/winhelper.h index 97d7042..6ff22a6 100644 --- a/server/winhelper.h +++ b/server/winhelper.h @@ -1,7 +1,14 @@ #ifndef _WINHELPER_H #define _WINHELPER_H -#define RTLD_LAZY 1 +static constexpr int RTLD_LAZY = 1; void* dlopen(const char*, int); void* dlsym(void*, const char*); int dlclose(void*); +struct SharedMemory +{ + void* hFileMap; + void* pData; + SharedMemory(const char*); + void FreeMemoryMap(); +}; #endif diff --git a/stock.a b/stock.a index f55ae52..8c194bf 100644 --- a/stock.a +++ b/stock.a @@ -17,13 +17,16 @@ INSERT INTO stocks VALUES(14,5) INSERT INTO stocks VALUES(15,2) INSERT INTO stocks VALUES(16,5) - "q1" - SELECT max(price-min(timestamp)) FROM stocks - "q2" +/* "q1" +*/ +SELECT max(price-mins(price)) FROM stocks +/* + "q2" SELECT price, timestamp FROM stocks where price -timestamp > 1 and not (price*timestamp<100); "q3" SELECT max(price-mins(price)) FROM stocks ASSUMING ASC timestamp +*/ \ No newline at end of file