178 lines
5.3 KiB
C++
178 lines
5.3 KiB
C++
#pragma once
|
|
|
|
#include "nasal_err.h"
|
|
#include "nasal_opcode.h"
|
|
#include "nasal_ast.h"
|
|
#include "ast_visitor.h"
|
|
#include "symbol_finder.h"
|
|
#include "nasal_parse.h"
|
|
#include "nasal_import.h"
|
|
|
|
#include "natives/builtin.h"
|
|
#include "natives/coroutine.h"
|
|
#include "natives/bits_lib.h"
|
|
#include "natives/math_lib.h"
|
|
#include "natives/fg_props.h"
|
|
#include "natives/io_lib.h"
|
|
#include "natives/json_lib.h"
|
|
#include "natives/dylib_lib.h"
|
|
#include "natives/regex_lib.h"
|
|
#include "natives/unix_lib.h"
|
|
#include "natives/subprocess.h"
|
|
|
|
#include <iomanip>
|
|
#include <list>
|
|
#include <stack>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning (disable:4244)
|
|
#pragma warning (disable:4267)
|
|
#endif
|
|
|
|
namespace nasal {
|
|
|
|
class codegen {
|
|
private:
|
|
error err;
|
|
|
|
// repl output flag, will generate op_repl to output stack top value if true
|
|
bool flag_need_repl_output = false;
|
|
|
|
// limit mode flag
|
|
bool flag_limited_mode = false;
|
|
|
|
// under limited mode, unsafe system api will be banned
|
|
const std::unordered_set<std::string> unsafe_system_api = {
|
|
// builtin
|
|
"__system", "__input", "__terminal_size",
|
|
// io
|
|
"__fout", "__open", "__write", "__stat"
|
|
// bits
|
|
"__fld", "__sfld", "__setfld",
|
|
"__buf",
|
|
// fg
|
|
"__logprint",
|
|
// dylib
|
|
"__dlopen", "__dlclose", "__dlcallv", "__dlcall",
|
|
// unix
|
|
"__chdir", "__environ", "__getcwd", "__getenv",
|
|
// subprocess
|
|
"__subprocess_create",
|
|
"__subprocess_active",
|
|
"__subprocess_terminate"
|
|
};
|
|
|
|
// file mapper for file -> index
|
|
std::unordered_map<std::string, usize> file_map;
|
|
void init_file_map(const std::vector<std::string>&);
|
|
|
|
// used for generate pop in return expression
|
|
std::vector<u32> in_foreach_loop_level;
|
|
|
|
// constant numbers and strings
|
|
std::unordered_map<f64, u64> const_number_map;
|
|
std::unordered_map<std::string, u64> const_string_map;
|
|
std::vector<f64> const_number_table;
|
|
std::vector<std::string> const_string_table;
|
|
|
|
// native functions
|
|
std::vector<nasal_builtin_table> native_function;
|
|
std::unordered_map<std::string, usize> native_function_mapper;
|
|
void load_native_function_table(nasal_builtin_table*);
|
|
void init_native_function();
|
|
|
|
// generated opcodes
|
|
std::vector<opcode> code;
|
|
|
|
// used to store jmp operands index, to fill the jump address back
|
|
std::list<std::vector<u64>> continue_ptr;
|
|
std::list<std::vector<u64>> break_ptr;
|
|
|
|
// symbol table
|
|
// global : max VM_STACK_DEPTH-1 values
|
|
std::unordered_map<std::string, u64> global;
|
|
|
|
// nasal namespace
|
|
// stores all global symbols of each file
|
|
std::unordered_map<std::string, std::unordered_set<std::string>> nasal_namespace;
|
|
|
|
// local : max 32768 upvalues 65536 values
|
|
// but in fact local scope also has less than VM_STACK_DEPTH value
|
|
std::list<std::unordered_map<std::string, u64>> local;
|
|
|
|
void check_id_exist(identifier*);
|
|
|
|
void die(const std::string& info, expr* node) {
|
|
err.err("code", node->get_location(), info);
|
|
}
|
|
|
|
void regist_number(const f64);
|
|
void regist_string(const std::string&);
|
|
void find_symbol(code_block*);
|
|
void regist_symbol(const std::string&);
|
|
i64 local_symbol_find(const std::string&);
|
|
i64 global_symbol_find(const std::string&);
|
|
i64 upvalue_symbol_find(const std::string&);
|
|
|
|
void emit(u8, u64, const span&);
|
|
|
|
void number_gen(number_literal*);
|
|
void string_gen(string_literal*);
|
|
void bool_gen(bool_literal*);
|
|
void vector_gen(vector_expr*);
|
|
void hash_gen(hash_expr*);
|
|
void func_gen(function*);
|
|
void call_gen(call_expr*);
|
|
void call_identifier(identifier*);
|
|
void call_hash_gen(call_hash*);
|
|
void null_access_gen(null_access*);
|
|
void call_vector_gen(call_vector*);
|
|
void call_func_gen(call_function*);
|
|
void mcall(expr*);
|
|
void mcall_identifier(identifier*);
|
|
void mcall_vec(call_vector*);
|
|
void mcall_hash(call_hash*);
|
|
void multi_def(definition_expr*);
|
|
void single_def(definition_expr*);
|
|
void definition_gen(definition_expr*);
|
|
void assignment_expression(assignment_expr*);
|
|
void gen_assignment_equal_statement(assignment_expr*);
|
|
void replace_left_assignment_with_load(const span&);
|
|
void assignment_statement(assignment_expr*);
|
|
void multi_assign_gen(multi_assign*);
|
|
void cond_gen(condition_expr*);
|
|
void loop_gen(expr*);
|
|
void load_continue_break(u64, u64);
|
|
void while_gen(while_expr*);
|
|
void for_gen(for_expr*);
|
|
void forei_gen(forei_expr*);
|
|
void statement_generation(expr*);
|
|
void or_gen(binary_operator*);
|
|
void and_gen(binary_operator*);
|
|
void unary_gen(unary_operator*);
|
|
void binary_gen(binary_operator*);
|
|
void null_chain_gen(binary_operator*);
|
|
void trino_gen(ternary_operator*);
|
|
void calc_gen(expr*);
|
|
void repl_mode_info_output_gen(expr*);
|
|
void block_gen(code_block*);
|
|
void ret_gen(return_expr*);
|
|
|
|
public:
|
|
const auto& strs() const {return const_string_table;}
|
|
const auto& nums() const {return const_number_table;}
|
|
const auto& natives() const {return native_function;}
|
|
const auto& codes() const {return code;}
|
|
const auto& globals() const {return global;}
|
|
|
|
public:
|
|
codegen() = default;
|
|
const error& compile(parse&, linker&, bool, bool);
|
|
void print(std::ostream&);
|
|
void symbol_dump(std::ostream&) const;
|
|
};
|
|
|
|
}
|