Merge pull request #60 from ValKmjolnir/develop

 create a demo formater
This commit is contained in:
ValK 2025-01-11 21:26:00 +08:00 committed by GitHub
commit fc2bb809aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 1114 additions and 340 deletions

View File

@ -17,10 +17,8 @@ jobs:
git push -f origin next_macOS
- name: Build
run: |
make -j4
cd module
make all -j4
cd ..
mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release
make -j6
- name: Test
run: make test
- name: Package
@ -33,7 +31,7 @@ jobs:
prerelease: true
draft: false
files: |
nasal-Darwin.tar
nasal-macOS-aarch64.tar
linux-x86_64-build:
runs-on: ubuntu-latest
@ -46,10 +44,8 @@ jobs:
git push -f origin next_linux_x86_64
- name: Build
run: |
make -j4
cd module
make all -j4
cd ..
mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release
make -j6
- name: Test
run: make test
- name: Package
@ -62,4 +58,4 @@ jobs:
prerelease: true
draft: false
files: |
nasal-Linux.tar
nasal-linux-x86_64.tar

View File

@ -14,10 +14,8 @@ jobs:
- uses: actions/checkout@v4
- name: Build
run: |
make -j4
cd module
make all -j4
cd ..
mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release
make -j6
- name: Test
run: make test
@ -27,9 +25,7 @@ jobs:
- uses: actions/checkout@v4
- name: Build
run: |
make -j4
cd module
make all -j4
cd ..
mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release
make -j6
- name: Test
run: make test

2
.gitignore vendored
View File

@ -50,7 +50,9 @@ cmake-windows-*
*.out
*.app
nasal
nasal-format
nasal.exe
nasal-format.exe
# Visual Studio specific
*.sln

View File

@ -9,7 +9,11 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall")
# MSVC does not need -fPIC
if (NOT MSVC)
add_compile_options(-fPIC)
endif()
# MSVC needs this command option to really enable utf-8 output
if (MSVC)
add_compile_options(/utf-8)
@ -19,9 +23,6 @@ if (APPLE)
add_compile_options(-mmacosx-version-min=10.15)
endif()
# generate release executables
set(CMAKE_BUILD_TYPE "Release")
# build nasal used object
set(NASAL_OBJECT_SOURCE_FILE
${CMAKE_SOURCE_DIR}/src/cli/cli.cpp
@ -40,6 +41,7 @@ set(NASAL_OBJECT_SOURCE_FILE
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
${CMAKE_SOURCE_DIR}/src/util/util.cpp
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
${CMAKE_SOURCE_DIR}/src/ast_format.cpp
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
@ -61,12 +63,18 @@ target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp)
target_link_libraries(nasal nasal-object)
# build nasal-format
add_executable(nasal-format ${CMAKE_SOURCE_DIR}/src/format.cpp)
target_link_libraries(nasal-format nasal-object)
# link ldl and lpthread
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
target_link_libraries(nasal dl)
target_link_libraries(nasal pthread)
target_link_libraries(nasal-format pthread)
endif()
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(nasal-format PRIVATE ${CMAKE_SOURCE_DIR}/src)
# copy nasal from build dir to the outside dir
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
@ -76,6 +84,12 @@ if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
${CMAKE_SOURCE_DIR}/build/nasal
${CMAKE_SOURCE_DIR}/nasal
)
add_custom_command(
TARGET nasal-format POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/build/nasal-format
${CMAKE_SOURCE_DIR}/nasal-format
)
endif()
# build module

View File

@ -10,7 +10,7 @@ Valid on powershell:
mkdir cmake-windows-msvc
cd cmake-windows-msvc
cmake .. -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022"
MSbuild.exe nasal.sln /p:Configuration=Release /p:Platform=x64
MSBuild.exe nasal.sln /p:Configuration=Release /p:Platform=x64
```
## MingW-W64

View File

@ -333,10 +333,10 @@ test:
@ ./nasal -t -d test/regex_test.nas
@ ./nasal -t -d test/replace_test.nas
@ ./nasal -e test/scalar.nas hello world
@ ./nasal test/subprocess_test.nas
@ ./nasal -e test/trait.nas
@ ./nasal -t test/subprocess_test.nas
@ ./nasal -t test/trait.nas
@ ./nasal -t -d test/turingmachine.nas
@ ./nasal -d test/wavecollapse.nas
@ ./nasal -d test/wavecity.nas
@ ./nasal test/word_collector.nas test/md5compare.nas
@ ./nasal -t -d test/wavecollapse.nas
@ ./nasal -t -d test/wavecity.nas
@ ./nasal -t test/word_collector.nas test/md5compare.nas
@ ./nasal -t -d test/ycombinator.nas

View File

@ -12,9 +12,9 @@ ifndef OS
OS = $(shell uname)
endif
ifeq ($(OS), Darwin)
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15 -I ../src
else
CXXFLAGS = -std=$(STD) -c -O3 -fPIC
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I ../src
endif
all: $(dynamic_libs_so)
@ -29,7 +29,7 @@ libfib.so: fib.cpp $(used_header) $(used_object)
@ rm fib.o
libfib.dll: fib.cpp $(used_header) $(used_object)
@ echo [Compiling] libfib.dll
@ $(CXX) -std=$(STD) -c -O3 fib.cpp -fPIC -o fib.o
@ $(CXX) -std=$(STD) -c -O3 fib.cpp -fPIC -o fib.o -I ../src
@ $(CXX) -shared -o libfib.dll fib.o $(used_object) -static
@ del fib.o
@ -40,7 +40,7 @@ libkey.so: keyboard.cpp $(used_header) $(used_object)
@ rm keyboard.o
libkey.dll: keyboard.cpp $(used_header) $(used_object)
@ echo [Compiling] libkey.dll
@ $(CXX) -std=$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o -static
@ $(CXX) -std=$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o -static -I ../src
@ $(CXX) -shared -o libkey.dll keyboard.o $(used_object) -static
@ del keyboard.o
@ -51,7 +51,7 @@ libnasock.so: nasocket.cpp $(used_header) $(used_object)
@ rm nasocket.o
libnasock.dll: nasocket.cpp $(used_header) $(used_object)
@ echo [Compiling] libnasock.dll
@ $(CXX) -std=$(STD) -c -O3 nasocket.cpp -fPIC -o nasocket.o -lwsock32 -static
@ $(CXX) -std=$(STD) -c -O3 nasocket.cpp -fPIC -I ../src -o nasocket.o -lwsock32 -static
@ $(CXX) -shared -o libnasock.dll nasocket.o $(used_object) -lwsock32 -static
@ del nasocket.o
@ -62,7 +62,7 @@ libmat.so: matrix.cpp $(used_header) $(used_object)
@ rm matrix.o
libmat.dll: matrix.cpp $(used_header) $(used_object)
@ echo [Compiling] libmat.dll
@ $(CXX) -std=$(STD) -c -O3 matrix.cpp -fPIC -o matrix.o -static
@ $(CXX) -std=$(STD) -c -O3 matrix.cpp -fPIC -I ../src -o matrix.o -static
@ $(CXX) -shared -o libmat.dll matrix.o $(used_object) -static
@ del matrix.o

412
src/ast_format.cpp Normal file
View File

@ -0,0 +1,412 @@
#include "ast_format.h"
#include "util/util.h"
#include <iostream>
namespace nasal {
bool ast_format::visit_use_stmt(use_stmt* node) {
dump_formating_node_info(node, "use statement");
out << "use ";
for(auto i : node->get_path()) {
i->accept(this);
if (i != node->get_path().back()) {
out << ".";
}
}
return true;
}
bool ast_format::visit_null_expr(null_expr* node) {
dump_formating_node_info(node, "null expression");
out << "null";
return true;
}
bool ast_format::visit_nil_expr(nil_expr* node) {
dump_formating_node_info(node, "nil expression");
out << "nil";
return true;
}
bool ast_format::visit_number_literal(number_literal* node) {
dump_formating_node_info(node, "number expression");
out << node->get_number();
return true;
}
bool ast_format::visit_string_literal(string_literal* node) {
dump_formating_node_info(node, "string expression");
out << "\"" << util::rawstr(node->get_content()) << "\"";
return true;
}
bool ast_format::visit_identifier(identifier* node) {
dump_formating_node_info(node, "identifier");
out << node->get_name();
return true;
}
bool ast_format::visit_bool_literal(bool_literal* node) {
dump_formating_node_info(node, "bool expression");
out << (node->get_flag()? "true" : "false");
return true;
}
bool ast_format::visit_vector_expr(vector_expr* node) {
dump_formating_node_info(node, "vector expression");
out << "[";
for(auto i : node->get_elements()) {
i->accept(this);
if (i != node->get_elements().back()) {
out << ", ";
}
}
out << "]";
return true;
}
bool ast_format::visit_hash_expr(hash_expr* node) {
dump_formating_node_info(node, "hash expression");
out << "{";
for(auto i : node->get_members()) {
i->accept(this);
if (i != node->get_members().back()) {
out << ", ";
}
}
out << "}";
return true;
}
bool ast_format::visit_hash_pair(hash_pair* node) {
dump_formating_node_info(node, "hash pair");
out << node->get_name();
if (node->get_value()) {
out << " : ";
node->get_value()->accept(this);
}
return true;
}
bool ast_format::visit_function(function* node) {
dump_formating_node_info(node, "function");
out << "func(";
for(auto i : node->get_parameter_list()) {
i->accept(this);
if (i != node->get_parameter_list().back()) {
out << ", ";
}
}
out << ") ";
node->get_code_block()->accept(this);
return true;
}
bool ast_format::visit_code_block(code_block* node) {
dump_formating_node_info(node, "code block");
out << "{\n";
push_indent();
for(auto i : node->get_expressions()) {
dump_indent();
i->accept(this);
if (need_dump_semi(i)) {
out << ";\n";
} else {
out << "\n";
}
}
pop_indent();
dump_indent();
out << "}";
return true;
}
bool ast_format::visit_parameter(parameter* node) {
dump_formating_node_info(node, "parameter");
out << node->get_parameter_name();
switch (node->get_parameter_type()) {
case parameter::kind::normal_parameter: break;
case parameter::kind::dynamic_parameter: out << "..."; break;
case parameter::kind::default_parameter: out << " = "; break;
}
if (node->get_default_value()) {
node->get_default_value()->accept(this);
}
return true;
}
bool ast_format::visit_ternary_operator(ternary_operator* node) {
dump_formating_node_info(node, "ternary operator");
node->get_condition()->accept(this);
out << " ? ";
node->get_left()->accept(this);
out << " : ";
node->get_right()->accept(this);
return true;
}
bool ast_format::visit_binary_operator(binary_operator* node) {
dump_formating_node_info(node, "binary operator");
out << "(";
node->get_left()->accept(this);
switch(node->get_operator_type()) {
case binary_operator::kind::add: out << " + "; break;
case binary_operator::kind::sub: out << " - "; break;
case binary_operator::kind::mult: out << " * "; break;
case binary_operator::kind::div: out << " / "; break;
case binary_operator::kind::concat: out << " ~ "; break;
case binary_operator::kind::bitwise_and: out << " & "; break;
case binary_operator::kind::bitwise_or: out << " | "; break;
case binary_operator::kind::bitwise_xor: out << " ^ "; break;
case binary_operator::kind::cmpeq: out << " == "; break;
case binary_operator::kind::cmpneq: out << " != "; break;
case binary_operator::kind::grt: out << " > "; break;
case binary_operator::kind::geq: out << " >= "; break;
case binary_operator::kind::less: out << " < "; break;
case binary_operator::kind::leq: out << " <= "; break;
case binary_operator::kind::condition_and: out << " and "; break;
case binary_operator::kind::condition_or: out << " or "; break;
case binary_operator::kind::null_chain: out << " ?? "; break;
}
node->get_right()->accept(this);
out << ")";
return true;
}
bool ast_format::visit_unary_operator(unary_operator* node) {
dump_formating_node_info(node, "unary operator");
switch(node->get_operator_type()) {
case unary_operator::kind::negative: out << "-"; break;
case unary_operator::kind::logical_not: out << "!"; break;
case unary_operator::kind::bitwise_not: out << "~"; break;
}
node->get_value()->accept(this);
return true;
}
bool ast_format::visit_call_expr(call_expr* node) {
dump_formating_node_info(node, "call expression");
node->get_first()->accept(this);
for(auto i : node->get_calls()) {
i->accept(this);
}
return true;
}
bool ast_format::visit_call_hash(call_hash* node) {
dump_formating_node_info(node, "call hash");
out << "." << node->get_field();
return true;
}
bool ast_format::visit_null_access(null_access* node) {
dump_formating_node_info(node, "null access operator(?.)");
out << "?." << node->get_field();
return true;
}
bool ast_format::visit_call_vector(call_vector* node) {
dump_formating_node_info(node, "call vector");
out << "[";
for(auto i : node->get_slices()) {
i->accept(this);
if (i != node->get_slices().back()) {
out << ", ";
}
}
out << "]";
return true;
}
bool ast_format::visit_call_function(call_function* node) {
dump_formating_node_info(node, "call function");
out << "(";
for(auto i : node->get_argument()) {
i->accept(this);
if (i != node->get_argument().back()) {
out << ", ";
}
}
out << ")";
return true;
}
bool ast_format::visit_slice_vector(slice_vector* node) {
dump_formating_node_info(node, "slice vector");
node->get_begin()->accept(this);
if (node->get_end()) {
out << " : ";
node->get_end()->accept(this);
}
return true;
}
bool ast_format::visit_definition_expr(definition_expr* node) {
dump_formating_node_info(node, "definition");
out << "var ";
if (node->get_variable_name()) {
node->get_variable_name()->accept(this);
} else {
node->get_variables()->accept(this);
}
out << " = ";
if (node->get_tuple()) {
node->get_tuple()->accept(this);
} else {
node->get_value()->accept(this);
}
return true;
}
bool ast_format::visit_assignment_expr(assignment_expr* node) {
dump_formating_node_info(node, "assignment");
node->get_left()->accept(this);
switch(node->get_assignment_type()) {
case assignment_expr::kind::add_equal: out << " += "; break;
case assignment_expr::kind::sub_equal: out << " -= "; break;
case assignment_expr::kind::mult_equal: out << " *= "; break;
case assignment_expr::kind::div_equal: out << " /= "; break;
case assignment_expr::kind::concat_equal: out << " ~= "; break;
case assignment_expr::kind::equal: out << " = "; break;
case assignment_expr::kind::bitwise_and_equal: out << " &= "; break;
case assignment_expr::kind::bitwise_or_equal: out << " |= "; break;
case assignment_expr::kind::bitwise_xor_equal: out << " ^= "; break;
}
node->get_right()->accept(this);
return true;
}
bool ast_format::visit_multi_identifier(multi_identifier* node) {
dump_formating_node_info(node, "multi identifier");
out << "(";
for(auto i : node->get_variables()) {
i->accept(this);
if (i != node->get_variables().back()) {
out << ", ";
}
}
out << ")";
return true;
}
bool ast_format::visit_tuple_expr(tuple_expr* node) {
dump_formating_node_info(node, "tuple expression");
out << "(";
for(auto i : node->get_elements()) {
i->accept(this);
if (i != node->get_elements().back()) {
out << ", ";
}
}
out << ")";
return true;
}
bool ast_format::visit_multi_assign(multi_assign* node) {
dump_formating_node_info(node, "multi assign");
node->get_tuple()->accept(this);
out << " = ";
node->get_value()->accept(this);
return true;
}
bool ast_format::visit_while_expr(while_expr* node) {
dump_formating_node_info(node, "while statement");
out << "while (";
node->get_condition()->accept(this);
out << ") ";
node->get_code_block()->accept(this);
return true;
}
bool ast_format::visit_for_expr(for_expr* node) {
dump_formating_node_info(node, "for statement");
out << "for (";
node->get_initial()->accept(this);
out << "; ";
node->get_condition()->accept(this);
out << "; ";
node->get_step()->accept(this);
out << ") ";
node->get_code_block()->accept(this);
return true;
}
bool ast_format::visit_iter_expr(iter_expr* node) {
dump_formating_node_info(node, "iteration expression");
if (node->is_definition()) {
out << "var ";
}
if (node->get_name()) {
node->get_name()->accept(this);
} else {
node->get_call()->accept(this);
}
return true;
}
bool ast_format::visit_forei_expr(forei_expr* node) {
dump_formating_node_info(node, "forindex/foreach statement");
if (node->get_loop_type()==forei_expr::kind::foreach) {
out << "foreach ";
} else {
out << "forindex ";
}
out << "(";
node->get_iterator()->accept(this);
out << "; ";
node->get_value()->accept(this);
out << ") ";
node->get_code_block()->accept(this);
return true;
}
bool ast_format::visit_condition_expr(condition_expr* node) {
dump_formating_node_info(node, "condition statement");
out << "if ";
node->get_if_statement()->accept(this);
for (auto i : node->get_elsif_stataments()) {
out << " elsif ";
i->accept(this);
}
if (node->get_else_statement()) {
out << " else ";
node->get_else_statement()->accept(this);
}
return true;
}
bool ast_format::visit_if_expr(if_expr* node) {
dump_formating_node_info(node, "if statement");
if (node->get_condition()) {
out << "(";
node->get_condition()->accept(this);
out << ") ";
}
node->get_code_block()->accept(this);
return true;
}
bool ast_format::visit_continue_expr(continue_expr* node) {
dump_formating_node_info(node, "continue statement");
out << "continue";
return true;
}
bool ast_format::visit_break_expr(break_expr* node) {
dump_formating_node_info(node, "break statement");
out << "break";
return true;
}
bool ast_format::visit_return_expr(return_expr* node) {
dump_formating_node_info(node, "return statement");
out << "return ";
if (node->get_value()) {
node->get_value()->accept(this);
}
return true;
}
}

144
src/ast_format.h Normal file
View File

@ -0,0 +1,144 @@
#pragma once
#include "ast_visitor.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <sstream>
#include <vector>
namespace nasal {
class ast_format: public ast_visitor {
private:
std::ofstream out;
std::vector<std::string> indent;
private:
void push_indent() {
indent.push_back(" ");
}
void pop_indent() {
if (indent.size()) {
indent.pop_back();
}
}
void dump_indent() {
for (const auto& i : indent) {
out << i;
}
}
void dump_formating_node_info(expr* n, const char* name) {
std::cout << " formating " << name << " @ 0x";
std::cout << std::hex << n << std::dec << "\n";
}
bool need_dump_semi(expr* n) {
switch (n->get_type()) {
case expr_type::ast_use:
case expr_type::ast_null:
case expr_type::ast_nil:
case expr_type::ast_num:
case expr_type::ast_str:
case expr_type::ast_bool:
case expr_type::ast_vec:
case expr_type::ast_hash:
case expr_type::ast_call: return true;
case expr_type::ast_def: {
auto dn = reinterpret_cast<definition_expr*>(n);
if (dn->get_value() &&
dn->get_value()->get_type() == expr_type::ast_func) {
return false;
}
return true;
}
case expr_type::ast_assign: {
auto dn = reinterpret_cast<assignment_expr*>(n);
if (dn->get_right() &&
dn->get_right()->get_type() == expr_type::ast_func) {
return false;
}
return true;
}
case expr_type::ast_ret: {
auto dn = reinterpret_cast<return_expr*>(n);
if (dn->get_value() &&
dn->get_value()->get_type() == expr_type::ast_func) {
return false;
}
return true;
}
default: break;
}
return false;
}
public:
bool visit_use_stmt(use_stmt*) override;
bool visit_null_expr(null_expr*) override;
bool visit_nil_expr(nil_expr*) override;
bool visit_number_literal(number_literal*) override;
bool visit_string_literal(string_literal*) override;
bool visit_identifier(identifier*) override;
bool visit_bool_literal(bool_literal*) override;
bool visit_vector_expr(vector_expr*) override;
bool visit_hash_expr(hash_expr*) override;
bool visit_hash_pair(hash_pair*) override;
bool visit_function(function*) override;
bool visit_code_block(code_block*) override;
bool visit_parameter(parameter*) override;
bool visit_ternary_operator(ternary_operator*) override;
bool visit_binary_operator(binary_operator*) override;
bool visit_unary_operator(unary_operator*) override;
bool visit_call_expr(call_expr*) override;
bool visit_call_hash(call_hash*) override;
bool visit_null_access(null_access*) override;
bool visit_call_vector(call_vector*) override;
bool visit_call_function(call_function*) override;
bool visit_slice_vector(slice_vector*) override;
bool visit_definition_expr(definition_expr*) override;
bool visit_assignment_expr(assignment_expr*) override;
bool visit_multi_identifier(multi_identifier*) override;
bool visit_tuple_expr(tuple_expr*) override;
bool visit_multi_assign(multi_assign*) override;
bool visit_while_expr(while_expr*) override;
bool visit_for_expr(for_expr*) override;
bool visit_iter_expr(iter_expr*) override;
bool visit_forei_expr(forei_expr*) override;
bool visit_condition_expr(condition_expr*) override;
bool visit_if_expr(if_expr*) override;
bool visit_continue_expr(continue_expr*) override;
bool visit_break_expr(break_expr*) override;
bool visit_return_expr(return_expr*) override;
public:
ast_format(const std::string output_file): out(output_file) {
if (out.fail()) {
throw std::runtime_error("can't open file: " + output_file);
}
}
void do_format(code_block* root) {
std::cout << "nasal-format is not stable right now, ";
std::cout << "take care of source code!\n";
dump_formating_node_info(root, "program root");
bool is_use_statement = true;
for (auto i : root->get_expressions()) {
if (is_use_statement && i->get_type() != expr_type::ast_use) {
is_use_statement = false;
out << "\n";
}
i->accept(this);
if (need_dump_semi(i)) {
out << ";\n";
} else {
out << "\n";
}
}
}
};
}

View File

@ -1,6 +1,12 @@
#include "nasal.h"
#include "cli/cli.h"
#include "util/util.h"
#include "nasal_parse.h"
#include <iostream>
#include <thread>
#include <cstdlib>
#include <ctime>
namespace nasal::cli {
@ -59,4 +65,75 @@ std::ostream& help(std::ostream& out) {
return out;
}
std::ostream& nasal_format_help(std::ostream& out) {
out
<< "\n"
<< " ,--#-,\n"
<< "<3 / \\____\\ <3\n"
<< " |_|__A_|\n"
<< "\nnasal-format <option>\n"
<< "option:\n"
<< " -h, --help | get help.\n"
<< " -v, --version | get version.\n"
<< "\nnasal-format <file>\n"
<< "file:\n"
<< " <filename> | file to be formatted.\n"
<< "\n";
return out;
}
std::ostream& logo(std::ostream& out) {
out
<< "\n"
<< " __ _\n"
<< " /\\ \\ \\__ _ ___ __ _| |\n"
<< " / \\/ / _` / __|/ _` | |\n"
<< " / /\\ / (_| \\__ \\ (_| | |\n"
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
<< "\n"
<< "ver : " << __nasver__
<< " " << nasal::util::get_platform()
<< " " << nasal::util::get_arch()
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
<< "std : c++ " << __cplusplus << "\n"
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
<< "repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
<< "\n"
<< "presented by fgprc members:\n"
<< " - http://fgprc.org\n"
<< " - http://fgprc.org.cn\n"
<< "\n"
<< "input <nasal-format -h> to get help.\n\n";
return out;
}
std::ostream& version(std::ostream& out) {
std::srand(static_cast<u32>(std::time(nullptr)));
f64 num = 0;
for(u32 i = 0; i<5; ++i) {
num = (num+rand())*(1.0/(RAND_MAX+1.0));
}
// give you 5% to see this easter egg
if (num<0.05) {
nasal::parse::easter_egg();
}
out << "nasal version " << __nasver__;
out << " " << nasal::util::get_platform();
out << " " << nasal::util::get_arch();
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
return out;
}
std::ostream& nasal_format_version(std::ostream& out) {
out << "nasal-format version " << __nasver__ << "-beta";
out << " " << nasal::util::get_platform();
out << " " << nasal::util::get_arch();
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
return out;
}
}

View File

@ -69,5 +69,10 @@ const std::unordered_map<std::string, option> cli_options = {
cli_config parse(const std::vector<std::string>&);
std::ostream& help(std::ostream&);
std::ostream& nasal_format_help(std::ostream&);
std::ostream& logo(std::ostream&);
std::ostream& version(std::ostream&);
std::ostream& nasal_format_version(std::ostream&);
}

56
src/format.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "nasal.h"
#include "nasal_lexer.h"
#include "nasal_ast.h"
#include "nasal_parse.h"
#include "util/util.h"
#include "cli/cli.h"
#include "ast_format.h"
#include <iostream>
#include <thread>
[[noreturn]]
void err() {
std::cerr << "invalid argument(s), use <nasal-format -h> to get help.\n";
std::exit(1);
}
void execute(const nasal::cli::cli_config& config) {
nasal::lexer lex;
nasal::parse parse;
// lexer scans file to get tokens
lex.scan(config.input_file_path).chkerr();
// parser gets lexer's token list to compile
parse.compile(lex).chkerr();
nasal::ast_format("nasal-format-out.nas").do_format(parse.tree());
}
int main(i32 argc, const char* argv[]) {
// output version info
if (argc <= 1) {
err();
} else if (argc > 2) {
err();
}
// the first argument is the executable itself, ignore it
const auto config = nasal::cli::parse({argv+1, argv+argc});
// run directly or show help
if (argc == 2) {
if (config.has(nasal::cli::option::cli_help)) {
std::clog << nasal::cli::nasal_format_help;
} else if (config.has(nasal::cli::option::cli_version)) {
std::clog << nasal::cli::nasal_format_version;
} else if (config.input_file_path.size()) {
execute(config);
} else {
err();
}
return 0;
}
return 0;
}

View File

@ -18,55 +18,8 @@
#include "repl/repl.h"
#include "cli/cli.h"
#include <thread>
#include <cstdlib>
std::ostream& logo(std::ostream& out) {
out
<< "\n"
<< " __ _\n"
<< " /\\ \\ \\__ _ ___ __ _| |\n"
<< " / \\/ / _` / __|/ _` | |\n"
<< " / /\\ / (_| \\__ \\ (_| | |\n"
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
<< "\n"
<< "ver : " << __nasver__
<< " " << nasal::util::get_platform()
<< " " << nasal::util::get_arch()
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
<< "std : c++ " << __cplusplus << "\n"
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
<< "repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
<< "\n"
<< "presented by fgprc members:\n"
<< " - http://fgprc.org\n"
<< " - http://fgprc.org.cn\n"
<< "\n"
<< "input <nasal -h> to get help.\n\n";
return out;
}
std::ostream& version(std::ostream& out) {
std::srand(static_cast<u32>(std::time(nullptr)));
f64 num = 0;
for(u32 i = 0; i<5; ++i) {
num = (num+rand())*(1.0/(RAND_MAX+1.0));
}
// give you 5% to see this easter egg
if (num<0.05) {
nasal::parse::easter_egg();
}
out << "nasal version " << __nasver__;
out << " " << nasal::util::get_platform();
out << " " << nasal::util::get_arch();
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
return out;
}
[[noreturn]]
void err() {
std::cerr << "invalid argument(s), use <nasal -h> to get help.\n";
@ -121,6 +74,7 @@ void execute(const nasal::cli::cli_config& config) {
// run
const auto start = clk::now();
double gc_time_ms = 0.0;
if (config.has(option::cli_debug_mode)) {
auto debugger = std::make_unique<nasal::dbg>();
debugger->run(
@ -130,6 +84,7 @@ void execute(const nasal::cli::cli_config& config) {
config.has(option::cli_profile),
config.has(option::cli_profile_all)
);
gc_time_ms = debugger->get_gc_time_ms();
} else if (config.has(option::cli_show_execute_time) ||
config.has(option::cli_detail_info) ||
config.has(option::cli_limit_mode) ||
@ -138,20 +93,25 @@ void execute(const nasal::cli::cli_config& config) {
runtime->set_detail_report_info(config.has(option::cli_detail_info));
runtime->set_limit_mode_flag(config.has(option::cli_limit_mode));
runtime->run(gen, ld, config.nasal_vm_args);
gc_time_ms = runtime->get_gc_time_ms();
}
// get running time
const auto end = clk::now();
if (config.has(option::cli_show_execute_time)) {
double execute_time_sec = static_cast<f64>((end - start).count())/den;
double gc_time_sec = gc_time_ms / 1000.0;
std::clog << "process exited after ";
std::clog << static_cast<f64>((end-start).count())/den << "s.\n\n";
std::clog << execute_time_sec << "s, gc time: ";
std::clog << gc_time_sec << "s (";
std::clog << gc_time_sec / execute_time_sec * 100.0 << "%)\n\n";
}
}
i32 main(i32 argc, const char* argv[]) {
// output version info
if (argc <= 1) {
std::clog << logo;
std::clog << nasal::cli::logo;
return 0;
}
@ -163,7 +123,7 @@ i32 main(i32 argc, const char* argv[]) {
if (config.has(nasal::cli::option::cli_help)) {
std::clog << nasal::cli::help;
} else if (config.has(nasal::cli::option::cli_version)) {
std::clog << version;
std::clog << nasal::cli::version;
} else if (config.has(nasal::cli::option::cli_repl_mode)) {
auto repl = std::make_unique<nasal::repl::repl>();
repl->execute();

View File

@ -1,7 +1,7 @@
#pragma once
#ifndef __nasver__
#define __nasver__ "11.3.1"
#define __nasver__ "11.3.2"
#endif
#include <cstddef>

View File

@ -94,6 +94,12 @@ public:
void context_change(nas_co*);
void context_reserve();
public:
double get_gc_time_ms() const {
const auto den = std::chrono::high_resolution_clock::duration::period::den;
return worktime * 1.0 / den * 1000.0;
}
public:
var newstr(char c) {
var s = alloc(vm_type::vm_str);

View File

@ -6,22 +6,6 @@
namespace nasal {
var nas_vec::get_value(const i32 index) {
i32 size = elems.size();
if (index<-size || index>=size) {
return var::none();
}
return elems[index>=0? index:index+size];
}
var* nas_vec::get_memory(const i32 index) {
i32 size = elems.size();
if (index<-size || index>=size) {
return nullptr;
}
return &elems[index>=0? index:index+size];
}
std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
if (!vec.elems.size() || vec.printed) {
out << (vec.elems.size()? "[..]":"[]");
@ -40,7 +24,8 @@ std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
var nas_hash::get_value(const std::string& key) {
if (elems.count(key)) {
return elems.at(key);
} else if (!elems.count("parents")) {
}
if (!elems.count("parents")) {
return var::none();
}
@ -63,7 +48,8 @@ var nas_hash::get_value(const std::string& key) {
var* nas_hash::get_memory(const std::string& key) {
if (elems.count(key)) {
return &elems.at(key);
} else if (!elems.count("parents")) {
}
if (!elems.count("parents")) {
return nullptr;
}
@ -279,12 +265,6 @@ void nas_val::clear() {
}
}
f64 var::to_num() const {
return type != vm_type::vm_str
? val.num
: util::str_to_num(str().c_str());
}
std::string var::to_str() {
if (type==vm_type::vm_str) {
return str();

View File

@ -1,6 +1,7 @@
#pragma once
#include "nasal.h"
#include "util/util.h"
#include <cstring>
#include <sstream>
@ -173,8 +174,13 @@ public:
bool is_map() const { return type == vm_type::vm_map; }
public:
// number and string can be translated to each other
f64 to_num() const;
// convert to number
f64 to_num() const {
return type != vm_type::vm_str
? val.num
: util::str_to_num(str().c_str());
}
// convert to string
std::string to_str();
inline bool object_check(const std::string&) const;
friend std::ostream& operator<<(std::ostream&, var&);
@ -187,8 +193,20 @@ struct nas_vec {
bool printed = false;
auto size() const { return elems.size(); }
var get_value(const i32);
var* get_memory(const i32);
var get_value(const i32 index) {
i32 size = elems.size();
if (index < -size || index >= size) {
return var::none();
}
return elems[index >= 0 ? index : index + size];
}
var* get_memory(const i32 index) {
i32 size = elems.size();
if (index < -size || index >= size) {
return nullptr;
}
return &elems[index >= 0 ? index : index + size];
}
friend std::ostream& operator<<(std::ostream&, nas_vec&);
};

View File

@ -254,7 +254,7 @@ void vm::function_call_trace() {
std::clog << "\ncall trace ";
std::clog << (ngc.cort? "(coroutine)":"(main)") << "\n";
std::clog << " crash occurred in\n ";
std::clog << " crash occurred at\n ";
function_detail_info(ctx.funcr.func());
std::clog << " at " << files[bytecode[ctx.pc].fidx] << ":";
std::clog << bytecode[ctx.pc].line << "\n";
@ -325,7 +325,7 @@ void vm::trace_back() {
// the first called place has no same calls
}
void vm::stack_info(const u64 limit = 16) {
void vm::stack_info(const u64 limit) {
var* top = ctx.top;
var* bottom = ctx.stack;
const auto stack_address = reinterpret_cast<u64>(bottom);
@ -525,8 +525,16 @@ std::string vm::type_name_string(const var& value) const {
void vm::die(const std::string& str) {
std::cerr << "[vm] error: " << str << "\n";
function_call_trace();
// trace back contains bytecode info, dump in verbose mode
if (verbose) {
trace_back();
stack_info();
}
// verbose will dump more values on stack
if (verbose) {
stack_info(64);
}
// show verbose crash info
if (verbose) {
@ -534,6 +542,9 @@ void vm::die(const std::string& str) {
}
if (!ngc.cort) {
if (!verbose) {
std::cerr << "\n[vm] use <-d> for detailed crash info.\n\n";
}
// in main context, exit directly
std::exit(1);
}

View File

@ -97,6 +97,7 @@ protected:
protected:
/* vm calculation functions*/
inline bool boolify(const var&);
inline void set_frame(const nas_func&, var*);
protected:
/* vm operands */
@ -318,6 +319,10 @@ public:
void set_limit_mode_flag(bool flag) {
flag_limited_mode = flag;
}
auto get_gc_time_ms() const {
return ngc.get_gc_time_ms();
}
};
inline bool vm::boolify(const var& val) {
@ -338,6 +343,15 @@ inline bool vm::boolify(const var& val) {
return false;
}
inline void vm::set_frame(const nas_func& func, var* local) {
ctx.top[0] = ctx.upvalr;
(++ctx.top)[0] = var::addr(ctx.localr);
(++ctx.top)[0] = var::ret(ctx.pc); // rewrite top with vm_ret
ctx.pc = func.entry - 1;
ctx.localr = local;
ctx.upvalr = nil;
}
inline void vm::o_repl() {
// reserved for repl mode stack top value output
if (allow_repl_output) {
@ -511,10 +525,10 @@ inline void vm::o_lnk() {
// concat two vectors into one
if (ctx.top[-1].is_vec() && ctx.top[0].is_vec()) {
ngc.temp = ngc.alloc(vm_type::vm_vec);
for(auto i : ctx.top[-1].vec().elems) {
for(auto& i : ctx.top[-1].vec().elems) {
ngc.temp.vec().elems.push_back(i);
}
for(auto i : ctx.top[0].vec().elems) {
for(auto& i : ctx.top[0].vec().elems) {
ngc.temp.vec().elems.push_back(i);
}
ctx.top[-1] = ngc.temp;
@ -847,12 +861,17 @@ inline void vm::o_callh() {
} else {
ctx.top[0] = val.map().get_value(str);
}
// report key not found if get_value returns none
if (ctx.top[0].is_none()) {
val.is_hash()?
die(report_key_not_found(str, val.hash())):
die("cannot find symbol \"" + str + "\"");
val.is_hash()
? die(report_key_not_found(str, val.hash()))
: die("cannot find symbol \"" + str + "\"");
return;
} else if (ctx.top[0].is_func()) {
}
// if get function from hash, set 'me'
if (ctx.top[0].is_func() && val.is_hash()) {
ctx.top[0].func().local[0] = val; // 'me'
}
}
@ -920,16 +939,13 @@ inline void vm::o_callfv() {
for(u64 i = min_size + 1; i<func.local_size; ++i) {
local[i] = func.local[i];
}
// load dynamic argument
local[func.dynamic_parameter_index>=0?
parameter_size+1:func.local_size-1] = dynamic;
ctx.top[0] = ctx.upvalr;
(++ctx.top)[0] = var::addr(ctx.localr);
(++ctx.top)[0] = var::ret(ctx.pc);
ctx.pc = func.entry-1;
ctx.localr = local;
ctx.upvalr = nil;
// load dynamic argument
local[func.dynamic_parameter_index >= 0
? parameter_size + 1
: func.local_size - 1] = dynamic;
set_frame(func, local);
}
inline void vm::o_callfh() {
@ -976,12 +992,7 @@ inline void vm::o_callfh() {
return;
}
ctx.top[0] = ctx.upvalr;
(++ctx.top)[0] = var::addr(ctx.localr);
(++ctx.top)[0] = var::ret(ctx.pc); // rewrite top with vm_ret
ctx.pc=func.entry-1;
ctx.localr = local;
ctx.upvalr = nil;
set_frame(func, local);
}
inline void vm::o_callb() {

View File

@ -18,14 +18,10 @@ void dynamic_library_destructor(void* pointer) {
#endif
}
std::string search_dynamic_library_path(const std::string& dlname) {
const auto ext = (util::is_windows()? ".dll":".so");
const auto lib_path = (util::is_windows()? ".\\":"./") + dlname + ext;
if (fs::exists(lib_path)) {
return lib_path;
}
std::vector<std::string> possible_dylib_path() {
const auto env_path = std::string(getenv("PATH"));
const auto sep = (util::is_windows()? ";":":");
const auto path_front = util::is_windows()? "\\module\\":"/module/";
// do split string
std::vector<std::string> env_path_vec = {"."};
@ -42,11 +38,44 @@ std::string search_dynamic_library_path(const std::string& dlname) {
env_path_vec.push_back(env_path.substr(last));
}
const auto path_front = util::is_windows()? "\\module\\":"/module/";
for (auto& p : env_path_vec) {
p += path_front + lib_path;
if (fs::exists(p)) {
return p;
p += path_front;
}
return env_path_vec;
}
std::string search_dynamic_library_path(const std::string& dlname) {
const auto ext = (util::is_windows()? ".dll":".so");
const auto lib_path = (util::is_windows()? ".\\":"./") + dlname + ext;
if (fs::exists(lib_path)) {
return lib_path;
}
// macos may use .dylib as extension
if (util::is_macos()) {
const auto dylib_path = "./" + dlname + ".dylib";
if (fs::exists(dylib_path)) {
return dylib_path;
}
}
// search library in PATH
const auto possible_path = possible_dylib_path();
for(const auto& p : possible_path) {
const auto env_p = p + lib_path;
if (fs::exists(env_p)) {
return env_p;
}
}
// macos may use .dylib as extension
if (util::is_macos()) {
const auto dylib_path = "./" + dlname + ".dylib";
for(const auto& p : possible_path) {
const auto env_p = p + dylib_path;
if (fs::exists(env_p)) {
return env_p;
}
}
}
return "";
@ -61,7 +90,7 @@ var builtin_dlopen(context* ctx, gc* ngc) {
const auto dlname = search_dynamic_library_path(dl.str());
if (dlname.empty()) {
return nas_err("dylib::dlopen",
"cannot find dynamic lib <" + dl.str() + ">"
"cannot find dynamic library <" + dl.str() + ">"
);
}

View File

@ -13,11 +13,13 @@
#include <cstring>
#include <sstream>
#include <vector>
namespace nasal {
void dynamic_library_destructor(void*);
std::vector<std::string> possible_dylib_path();
std::string search_dynamic_library_path(const std::string&);
var builtin_dlopen(context*, gc*);

View File

@ -16,8 +16,8 @@ var ppm = func(filename, width, height, RGB) {
io.close(fd);
}
var width = 1920;
var height = 1080;
var width = 1920 * 2;
var height = 1080 * 2;
var bar = (os.platform()=="windows")?
process_bar.bar(front:"sharp", back:"point", sep:"line", length:50):
process_bar.high_resolution_bar(50);

View File

@ -31,6 +31,7 @@ func() {
runtime.gc.extend("vec", 8);
}();
# alias
var (max, min, sqrt, sin, cos, abs) = (
math.max,
math.min,
@ -76,19 +77,41 @@ var use_raw = func() {
vec2sub = func(v1, v2) {return [v1[0]-v2[0],v1[1]-v2[1]];}
vec2mul = func(v1, v2) {return [v1[0]*v2[0],v1[1]*v2[1]];}
vec2div = func(v1, v2) {return [v1[0]/v2[0],v1[1]/v2[1]];}
vec2len = func(v) {var (x,y)=(v[0],v[1]); return sqrt(x*x+y*y);}
vec3 = func(x, y, z) {return [x,y,z];}
vec3add = func(v1, v2) {return [v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]];}
vec3sub = func(v1, v2) {return [v1[0]-v2[0],v1[1]-v2[1],v1[2]-v2[2]];}
vec3mul = func(v1, v2) {return [v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]];}
vec3div = func(v1, v2) {return [v1[0]/v2[0],v1[1]/v2[1],v1[2]/v2[2]];}
vec3neg = func(v) {return [-v[0],-v[1],-v[2]];}
vec2len = func(v) {var (x,y)=(v[0],v[1]); return sqrt(x*x+y*y);}
vec3len = func(v) {var (x,y,z)=(v[0],v[1],v[2]); return sqrt(x*x+y*y+z*z);}
vec3norm = func(v) {var t=vec3len(v); return vec3div(v,[t,t,t]);}
vec3dot = func(a,b) {return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}
rotateX = func(a,angle) {return [a[0],a[2]*sin(angle)+a[1]*cos(angle),a[2]*cos(angle)-a[1]*sin(angle)];}
rotateY = func(a,angle) {return [a[0]*cos(angle)-a[2]*sin(angle),a[1],a[0]*sin(angle)+a[2]*cos(angle)];}
rotateZ = func(a,angle) {return [a[0]*cos(angle)-a[1]*sin(angle),a[0]*sin(angle)+a[1]*cos(angle),a[2]];}
vec3dot = func(a, b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
rotateX = func(a, angle) {
return [
a[0],
a[2] * sin(angle) + a[1] * cos(angle),
a[2] * cos(angle) - a[1] * sin(angle)
];
}
rotateY = func(a, angle) {
return [
a[0] * cos(angle) - a[2] * sin(angle),
a[1],
a[0] * sin(angle) + a[2] * cos(angle)
];
}
rotateZ = func(a, angle) {
return [
a[0] * cos(angle) - a[1] * sin(angle),
a[0] * sin(angle) + a[1] * cos(angle),
a[2]
];
}
}
var clamp = func(value, _min, _max) {
@ -108,7 +131,11 @@ var vec3sign = func(v) {
return [sign(v[0]), sign(v[1]), sign(v[2])];
}
var vec3step = func(edge, v) {
return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])];
return [
step(edge[0], v[0]),
step(edge[1], v[1]),
step(edge[2], v[2])
];
}
var vec3reflect = func(rd, n) {
var d = vec3dot(n, rd);
@ -119,7 +146,8 @@ var sphere = func(ro,rd,r) {
var b = vec3dot(ro, rd);
var c = vec3dot(ro, ro) - r * r;
var h = b * b - c;
if (h<0.0) return [-1.0,-1.0];
if (h < 0.0)
return [-1.0, -1.0];
h = sqrt(h);
return [-b - h, -b + h];
}
@ -132,10 +160,14 @@ var box = func(ro,rd,boxSize,outNormal) {
var t2 = vec3add(vec3neg(n), k);
var tN = max(max(t1[0], t1[1]), t1[2]);
var tF = min(min(t2[0], t2[1]), t2[2]);
if (tN>tF or tF<0.0) return [-1.0,-1.0];
if (tN>tF or tF<0.0)
return [-1.0, -1.0];
var yzx = [t1[1], t1[2], t1[0]];
var zxy = [t1[2], t1[0], t1[1]];
var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1));
var tmp = vec3mul(
vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx, t1)),
vec3step(zxy, t1)
);
outNormal[0] = tmp[0];
outNormal[1] = tmp[1];
outNormal[2] = tmp[2];
@ -232,19 +264,25 @@ var main = func(frame) {
var st = maketimestamp();
var run = [0, 0];
var frame = 1e3;
# reset required frame if given
if (size(runtime.argv()) != 0) {
var n = num(runtime.argv()[0]);
if (!math.isnan(n)) {
frame = n;
}
}
st.stamp();
main(frame);
run[0] = st.elapsedMSec();
# switch used matrix library
use_raw();
st.stamp();
main(frame);
run[1] = st.elapsedMSec();
println("test 0: ",run[0]/1000,"s ",frame*1000/run[0]," fps");
println("test 1: ",run[1]/1000,"s ",frame*1000/run[1]," fps");
println("total frame: ", frame);
println("test [0]: ", run[0]/1000, "s with ", frame*1000/run[0], " fps");
println("test [1]: ", run[1]/1000, "s with ", frame*1000/run[1], " fps");

View File

@ -16,25 +16,29 @@ var ppm = func(filename, width, height, RGB) {
io.close(fd);
}
var width = 1920;
var height = 1080;
var width = 1920 * 2;
var height = 1080 * 2;
var bar = (os.platform()=="windows")?
process_bar.bar(front:"sharp", back:"point", sep:"line", length:50):
process_bar.high_resolution_bar(50);
var abs = math.abs; # alias
var RGB = func(h, w) {
var r = 2+w*2/width;
var x = (height-h)/height;
var res = 0;
var (R, G, B) = (0, 0, 0);
var tmp = 0.5;
for(var i = 0; i<50; i+=1) {
tmp = r*tmp*(1-tmp);
}
for(var i = 0; i<100; i+=1) {
for(var i = 0; i<150; i+=1) {
tmp = r*tmp*(1-tmp);
if (math.abs(tmp-x)<0.001) {
res = 255;
if (abs(tmp-x)<0.0005) {
R = int(255*(150 - i)/150);
G = int(255*(150 - i)/150);
B = 255;
break;
}
}
@ -44,8 +48,7 @@ var RGB = func(h, w) {
print(bar.bar(progress), " ", progress*100, "% \r");
}
var c = char(res);
return c~c~c;
return char(R) ~ char(G) ~ char(B);
}
ppm("feigenbaum.ppm", width, height, RGB);

View File

@ -6,7 +6,7 @@ for(var yPixel=0;yPixel<24;yPixel+=1) {
var x = (xPixel/80)*xDel+xMin;
var pixel = " ";
var (x0, y0) = (x, y);
for(var iter=0;iter<80;iter+=1) {
for(var iter = 0; iter < 100; iter += 1) {
var x1 = (x0*x0)-(y0*y0)+x;
var y1 = 2*x0*y0+y;
(x0, y0) = (x1, y1);
@ -19,4 +19,5 @@ for(var yPixel=0;yPixel<24;yPixel+=1) {
}
line ~= '\n';
}
print(line);

View File

@ -15,8 +15,8 @@ var ppm = func(filename, width, height, RGB) {
io.close(fd);
}
var width = 1920;
var height = 1080;
var width = 1920 * 2;
var height = 1080 * 2;
var bar = (os.platform()=="windows")?
process_bar.bar(front:"sharp", back:"point", sep:"line", length:50):
process_bar.high_resolution_bar(50);

View File

@ -10,10 +10,14 @@ if not os.path.exists(build_directory):
exit(-1)
nasal_executable = pathlib.Path("nasal")
nasal_format_executable = pathlib.Path("nasal-format")
nasal_standard_library = pathlib.Path("std")
if not os.path.exists(nasal_executable):
print("pack binaries failed: nasal executable not found")
exit(-1)
if not os.path.exists(nasal_format_executable):
print("pack binaries failed: nasal-format executable not found")
exit(-1)
if not os.path.exists(nasal_standard_library):
print("pack binaries failed: nasal standard library not found")
exit(-1)
@ -43,7 +47,15 @@ for m in ["libfib", "libkey", "libmat", "libnasock"]:
nasal_modules.append(lib)
tar_file_name = "nasal-{}".format(platform.system())
tar_file_name = "nasal"
if platform.system()=="Windows":
tar_file_name += "-windows-x86_64"
elif platform.system()=="Linux":
tar_file_name += "-linux-x86_64"
elif platform.system()=="Darwin":
tar_file_name += "-macos-aarch64"
else:
print("pack binaries failed: unsupported platform")
# create package directory in build directory and copy files needed
package_directory = build_directory.joinpath(tar_file_name)
@ -53,6 +65,7 @@ if not os.path.exists(package_directory):
print("pack nasal executable")
shutil.copy(nasal_executable, package_directory.joinpath(nasal_executable))
shutil.copy(nasal_format_executable, package_directory.joinpath(nasal_format_executable))
print("pack nasal standard library")
shutil.copytree(nasal_standard_library, package_directory.joinpath(nasal_standard_library))