diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml new file mode 100644 index 0000000..449834a --- /dev/null +++ b/.github/workflows/ccpp.yml @@ -0,0 +1,15 @@ +name: C/C++ CI + +on: [push] + +jobs: + linux-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: install + run: sudo apt install llvm-7-dev + - name: cmake configure + run: cmake . + - name: cmake build + run: cmake --build . diff --git a/CMakeLists.txt b/CMakeLists.txt index bb2ec59..1141b64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 2.8.7) project(Jet) -find_package(LLVM 6.0.0 REQUIRED CONFIG HINTS C:/users/space/desktop/llvm/llvm-6.0.0.src) +find_package(LLVM 7.0.0 REQUIRED CONFIG HINTS C:/users/space/desktop/llvm/llvm-7.0.0.src) #find_package(Clang REQUIRED CONFIG HINTS C:/Users/space/Desktop/cfe-3.7.1.src) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") @@ -19,10 +19,10 @@ message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") include_directories(${LLVM_INCLUDE_DIRS})# ${CLANG_INCLUDE_DIR}) add_definitions(${LLVM_DEFINITIONS}) -get_cmake_property(_variableNames VARIABLES) -foreach (_variableName ${_variableNames}) - message(STATUS "${_variableName}=${${_variableName}}") -endforeach() +#get_cmake_property(_variableNames VARIABLES) +#foreach (_variableName ${_variableNames}) +# message(STATUS "${_variableName}=${${_variableName}}") +#endforeach() include_directories("${PROJECT_BINARY_DIR}" )# "C:/Users/Matthew/Desktop/cfe-3.7.1.src/include") @@ -49,27 +49,6 @@ add_executable(Jet source_group(Types REGULAR_EXPRESSION Types/*) -add_library(Racer - SHARED - - racer.cpp - - Compiler.cpp - CompilerContext.cpp - Expressions.cpp - ControlExpressions.cpp - DeclarationExpressions.cpp - Parser.cpp - Parselets.cpp - Source.cpp - Types/Types.cpp - Types/Function.cpp - Lexer.cpp - Token.cpp - Project.cpp - Compilation.cpp - ) - include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) @@ -84,9 +63,8 @@ endif() # target_compile_features(Racer PRIVATE cxx_range_for) # target_compile_features(Jet PRIVATE cxx_range_for) -llvm_map_components_to_libnames(llvm_libs support core mcjit native ipo) +llvm_map_components_to_libnames(llvm_libs support core mcjit native ipo ARM) # Link against LLVM libraries target_link_libraries(Jet ${llvm_libs})# "C:/Users/Matthew/Desktop/cfe-3.7.1.src/Debug/lib/libclang.lib") -target_link_libraries(Racer ${llvm_libs}) \ No newline at end of file diff --git a/Compilation.cpp b/Compilation.cpp index 6fad1c3..2615475 100644 --- a/Compilation.cpp +++ b/Compilation.cpp @@ -51,7 +51,7 @@ using namespace Jet; #endif -std::string Jet::exec(const char* cmd) { +std::string Jet::exec(const char* cmd, int* error_code) { #ifdef _WIN32 FILE* pipe = _popen(cmd, "r"); #else @@ -65,10 +65,14 @@ std::string Jet::exec(const char* cmd) { result += buffer; } #ifdef _WIN32 - _pclose(pipe); + auto res = _pclose(pipe); #else - pclose(pipe); + auto res = pclose(pipe); #endif + if (error_code) + { + *error_code = WEXITSTATUS(res); + } return result; } @@ -166,14 +170,14 @@ class StackTime public: long long start; long long rate; - char* name; + const char* name; - StackTime(char* name, bool enable = true); + StackTime(const char* name, bool enable = true); ~StackTime(); }; -StackTime::StackTime(char* name, bool time) +StackTime::StackTime(const char* name, bool time) { this->name = name; this->enable = time; @@ -317,6 +321,7 @@ Compilation* Compilation::Make(JetProject* project, DiagnosticBuilder* diagnosti //add default defines auto defines = project->defines; + // todo dont hardcode this so we can do cross compilation (eventually) #ifdef _WIN32 defines["WINDOWS"] = true; #else @@ -328,9 +333,9 @@ Compilation* Compilation::Make(JetProject* project, DiagnosticBuilder* diagnosti defines["RELEASE"] = true; //build converted headers and add their source - for (auto hdr : project->headers) + for (const auto& hdr_name : project->headers) { - std::string two = hdr; + std::string two = hdr_name; std::string outfile = two + ".jet"; //if the header already exists, dont regenerate FILE* hdr = fopen(outfile.c_str(), "r"); @@ -465,8 +470,6 @@ Compilation* Compilation::Make(JetProject* project, DiagnosticBuilder* diagnosti //this fixes some errors, need to resolve them later compilation->debug_info.file = compilation->debug->createFile("temp", compilation->debug_info.cu->getDirectory()); - - //compilation->ResolveTypes(); } compilation->ResolveTypes(); compilation->compiling_includes = false; @@ -592,18 +595,33 @@ Compilation* Compilation::Make(JetProject* project, DiagnosticBuilder* diagnosti } } - //figure out how to get me working with multiple definitions - /*auto init = global->AddFunction("_jet_initializer", compilation->ns->members.find("int")->second.ty, {}, false, false); + // Generate initializers. if (project->IsExecutable()) { - //this->builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, init->function->scope.get())); - //init->Call("puts", { init->String("hello from initializer") }); + // Clear the debug location for this autogenerated function + compilation->builder.SetCurrentDebugLocation(0); - //todo: put intializers here - if (project->IsExecutable()) - init->Call("main", {}); + // Executables need an _init function + auto func = new Function("_init", false, true); + func->return_type = &VoidType; + compilation->functions.push_back(func); + + auto n = new CompilerContext(compilation, 0); + n->function = func; + func->context = n; + compilation->ns->members.insert({ func->name, func }); + + compilation->current_function = n; + func->Load(compilation); + llvm::BasicBlock *bb = llvm::BasicBlock::Create(compilation->context, "entry", func->f); + compilation->builder.SetInsertPoint(bb); + + compilation->builder.CreateRetVoid(); + } + else + { + // Each library needs an appropriately named initialization function } - init->Return(global->Integer(0));*/ error: @@ -687,7 +705,12 @@ void Compilation::Assemble(const std::string& target, const std::string& linker, //add string //linux i686-pc-linux-gnu //raspbian arm-pc-linux-gnueabif"armv6-linux-gnueabihf" - this->SetTarget(target); + std::string real_target = this->SetTarget(target); + + // now lets split apart the target to get the arch, OS and stdlib (ignoring the second bit) + std::string target_arch = real_target.substr(0, real_target.find_first_of('-')); + std::string target_platform = "linux";// for the moment + std::string target_stdlib = real_target.substr(real_target.find_last_of('-')+1); debug->finalize(); @@ -725,13 +748,56 @@ void Compilation::Assemble(const std::string& target, const std::string& linker, if (used_linker.find("link.exe") == -1) { - std::string cmd = linker + " ";// "ld ";//"gcc -L. -g ";//-e_jet_initializer + std::string cmd = linker + " "; //set entry - cmd += "--entry _main "; + + // Set the dynamic linker correctly (for linux) + std::string stdlib = real_target.substr(real_target.find_last_of('-')+1); + if (target_stdlib == "musl" && target_platform == "linux") + { + cmd += "--dynamic-linker=/lib/ld-musl-" + target_arch + ".so.1 "; + } + else if (target_platform == "linux") + { + std::string arch = target_arch; + for (auto& c: arch) + { + if (c == '_') c = '-'; + } + if (target_arch.find("64") == -1) + { + cmd += "--dynamic-linker=/lib/ld-" + target_platform + "-" + arch + ".so.3 "; + } + else + { + cmd += "--dynamic-linker=/lib64/ld-" + target_platform + "-" + arch + ".so.2 "; + } + } + + // always link in C for the moment, eventually have a way to avoid this + if (target_platform == "linux") + { + cmd += "-L/lib/" + target_arch + "-" + target_platform + "-" + target_stdlib + " "; + cmd += "-lc "; + cmd += "/usr/lib/" + target_arch + "-" + target_platform + "-" + target_stdlib + "/crt1.o "; + if (target_stdlib == "gnu") + { + cmd += "/usr/lib/" + target_arch + "-" + target_platform + "-gnu/libc_nonshared.a "; + } + } + else + { + // todo link in C for windows (maybe this works) + //cmd += " -lc "; + } + + // for when we dont use C + //cmd += "--entry _main "; cmd += "\"build/" + project->project_name + ".o\" "; - cmd += "-o \"build/" + project->project_name + ".exe\" "; + std::string extension = target_platform == "linux" ? "" : ".exe"; + cmd += "-o \"build/" + project->project_name + extension + "\" "; //todo need to make sure to link in deps of deps also fix linking //need to link each dependency for (auto ii : project->ResolveDependencies()) @@ -770,8 +836,15 @@ void Compilation::Assemble(const std::string& target, const std::string& linker, //rename _context into this in generators, figure out why passing by value into async doesnt work // implement basic containers printf("\n%s\n", cmd.c_str()); - auto res = exec(cmd.c_str()); - printf(res.c_str()); + int code; + auto res = exec(cmd.c_str(), &code); + printf("%s", res.c_str()); + + if (code) + { + this->diagnostics->Error("Linking failed.", Token()); + return; + } } else { @@ -815,7 +888,7 @@ void Compilation::Assemble(const std::string& target, const std::string& linker, auto res = exec(cmd.c_str()); - printf(res.c_str()); + printf("%s", res.c_str()); } } else @@ -840,7 +913,7 @@ void Compilation::Assemble(const std::string& target, const std::string& linker, //can use llvm-ar or just ar std::string cm = ar + " x " + ii + "/build/lib" + GetNameFromPath(ii) + ".a"; auto res = exec(cm.c_str()); - printf(res.c_str()); + printf("%s", res.c_str()); //get a list of the extracted files cm = ar + " t " + ii + "/build/lib" + GetNameFromPath(ii) + ".a"; @@ -862,15 +935,17 @@ void Compilation::Assemble(const std::string& target, const std::string& linker, } auto res = exec(cmd.c_str()); - printf(res.c_str()); + printf("%s", res.c_str()); //delete temporary files for (auto ii : temps) + { #ifndef _WIN32 remove(ii.c_str()); #else DeleteFileA(ii.c_str()); #endif + } } //restore working directory @@ -896,14 +971,14 @@ void Compilation::Optimize(int level) // Provide basic AliasAnalysis support for GVN. //OurFPM.add(llvm::createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. - OurFPM.add(llvm::createInstructionCombiningPass()); + //OurFPM.add(llvm::createInstructionCombiningPass()); // Reassociate expressions. OurFPM.add(llvm::createReassociatePass()); - OurFPM.add(llvm::createInstructionSimplifierPass()); + //OurFPM.add(llvm::createInstructionSimplifierPass()); // Promote allocas to registers - OurFPM.add(llvm::createPromoteMemoryToRegisterPass()); + //OurFPM.add(llvm::createPromoteMemoryToRegisterPass()); // Eliminate Common SubExpressions. //OurFPM.add(llvm::createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). @@ -924,16 +999,18 @@ void Compilation::Optimize(int level) } } -#include -void Compilation::SetTarget(const std::string& triple) +//#include +std::string Compilation::SetTarget(const std::string& triple) { llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetAsmPrinter(); - //LLVMInitializeARMTarget(); - //LLVMInitializeARMAsmPrinter(); - //LLVMInitializeARMTargetMC(); - //LLVMInitializeARMTargetInfo(); + //LLVMInitializeAllTargets(); + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTarget(); + LLVMInitializeARMTargetMC(); + LLVMInitializeARMAsmPrinter(); + LLVMInitializeARMAsmParser(); //LLVMInitializeMSP430Target(); //llvm::initializeTarget() @@ -951,6 +1028,13 @@ void Compilation::SetTarget(const std::string& triple) TheTriple.setTriple(llvm::sys::getDefaultTargetTriple()); } + printf("Assembling as %s\n", TheTriple.str().c_str()); + + + //std::error_code ec; + //llvm::raw_fd_ostream strr("build/targets", ec, llvm::sys::fs::OpenFlags::F_None); + //llvm::TargetRegistry::printRegisteredTargetsForVersion(strr); + //ok, now for linux builds... //TheTriple = llvm::Triple("i686", "pc", "linux", "gnu"); // Get the target specific parser. @@ -987,6 +1071,8 @@ void Compilation::SetTarget(const std::string& triple) this->target = TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, Options, RelocModel, CodeModel, OLvl); module->setDataLayout(this->target->createDataLayout()); + + return TheTriple.str().c_str(); } void Compilation::OutputPackage(const std::string& project_name, int o_level, bool time) @@ -997,14 +1083,13 @@ void Compilation::OutputPackage(const std::string& project_name, int o_level, bo llvm::raw_fd_ostream strr("build/" + project_name + ".o", ec, llvm::sys::fs::OpenFlags::F_None); //ok, watch out for unsupported calling conventions, need way to specifiy code for windows/linux/cpu //add pass to emit the object file - target->addPassesToEmitFile(MPM, strr, llvm::TargetMachine::CodeGenFileType::CGFT_ObjectFile, false); + target->addPassesToEmitFile(MPM, strr, 0, llvm::TargetMachine::CodeGenFileType::CGFT_ObjectFile, false); //std::error_code ecc; //llvm::raw_fd_ostream strrr("build/" + project_name + ".s", ecc, llvm::sys::fs::OpenFlags::F_RW); //llvm::formatted_raw_ostream oo2(strrr); //target->addPassesToEmitFile(MPM, strrr, llvm::TargetMachine::CodeGenFileType::CGFT_AssemblyFile, false); - MPM.run(*module); //auto mod = JITHelper->getModuleForNewFunction(); @@ -1101,7 +1186,7 @@ Jet::Type* Compilation::TryLookupType(const std::string& name) return this->LookupType(name, false, false); } -Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_error) +Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_error, int start_index) { unsigned int i = 0; while (IsLetter(name[i]) || IsNumber(name[i])) @@ -1118,13 +1203,20 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e if (res == this->ns->members.end()) { if (do_error) - this->Error("Namespace " + ns + " not found", *this->current_function->current_token); + { + // Make a new token for this error + Token relevant_token = *this->current_function->current_token; + relevant_token.text = relevant_token.text.substr(0, i); + this->Error("Namespace '" + ns + "' not found", relevant_token); + } else + { return 0; + } } auto old = this->ns; this->ns = res->second.ns; - auto out = this->LookupType(name.substr(i + 2), load, do_error); + auto out = this->LookupType(name.substr(i + 2), load, do_error, start_index + i + 2); this->ns = old; return out; @@ -1170,7 +1262,7 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e else if (name[name.length() - 1] == '*') { //its a pointer - auto t = this->LookupType(name.substr(0, name.length() - 1), load, do_error); + auto t = this->LookupType(name.substr(0, name.length() - 1), load, do_error, start_index); if (t->pointer_type) return t->pointer_type; @@ -1198,7 +1290,7 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e auto len = name.substr(p + 1, name.length() - p - 2); auto tname = name.substr(0, p); - auto t = this->LookupType(tname, load, do_error); + auto t = this->LookupType(tname, load, do_error, start_index); if (len.length()) { @@ -1224,15 +1316,15 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e p++; do { - //lets cheat for the moment ok + int cur_index = start_index + p; std::string subtype = ParseType(name.c_str(), p); - Type* t = this->LookupType(subtype, load, do_error); + Type* t = this->LookupType(subtype, load, do_error, cur_index); types.push_back(t); } while (name[p++] != '>'); //look up the base, and lets instantiate it - auto t = this->LookupType(base, false, do_error); + auto t = this->LookupType(base, false, do_error, start_index); type = t->Instantiate(this, types); } @@ -1264,7 +1356,7 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e } std::string ret_type = name.substr(0, p); - auto rtype = this->LookupType(ret_type, load, do_error); + auto rtype = this->LookupType(ret_type, load, do_error, start_index); std::vector args; //parse types @@ -1272,9 +1364,10 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e while (name[p] != ')') { //lets cheat for the moment ok + int cur_index = start_index + p; std::string subtype = ParseType(name.c_str(), p); - Type* t = this->LookupType(subtype, load, do_error); + Type* t = this->LookupType(subtype, load, do_error, cur_index); args.push_back(t); if (name[p] == ',') p++; @@ -1285,7 +1378,16 @@ Jet::Type* Compilation::LookupType(const std::string& name, bool load, bool do_e else { if (do_error) - Error("Reference To Undefined Type '" + name + "'", *this->current_function->current_token); + { + Token tok = *this->current_function->current_token; + if (start_index > 0) + { + // need to create a special token as we are into a type + tok.text = tok.text.substr(start_index, name.length()); + tok.column += start_index; + } + Error("Reference To Undefined Type '" + name + "'", tok); + } else return 0; } @@ -1329,12 +1431,12 @@ CValue Compilation::AddGlobal(const std::string& name, Jet::Type* t, int size, l type = llvm::ArrayType::get(t->GetLLVMType(), size); ret_type = my_type = new_type->GetPointerType(); } - auto ng = new llvm::GlobalVariable(*module, type, false, intern ? llvm::GlobalValue::LinkageTypes::InternalLinkage : llvm::GlobalValue::LinkageTypes::CommonLinkage/*ExternalLinkage*/, initializer, name); + auto ng = new llvm::GlobalVariable(*module, type, false, intern ? llvm::GlobalValue::LinkageTypes::InternalLinkage : llvm::GlobalValue::LinkageTypes::WeakODRLinkage/*ExternalLinkage*/, initializer, name); this->debug->createGlobalVariableExpression(this->debug_info.file, name, name, this->debug_info.file, this->current_function->current_token->line, t->GetDebugType(this), !intern); this->ns->members.insert({ name, Symbol(new CValue(my_type, ng)) }); - //if it has a constructor, make sure to call it + //todo if it has a constructor, make sure to call it in the initializers... return CValue(ret_type, ng); } @@ -1345,6 +1447,13 @@ void Compilation::Error(const std::string& string, Token token) throw 7; } +void Compilation::Error(const std::string& string, const Token& start, const Token& end) +{ + this->diagnostics->Error(string, start, end); + + throw 7; +} + Jet::Type* Compilation::GetArrayType(Jet::Type* base) { auto res = this->array_types.find(base); @@ -1373,9 +1482,9 @@ Jet::Type* Compilation::GetInternalArrayType(Jet::Type* base, unsigned int size) ::Jet::Type* Compilation::GetFunctionType(::Jet::Type* return_type, const std::vector<::Jet::Type*>& args) { - int key = (int)return_type; + int key = (uintptr_t)return_type; for (auto arg : args) - key ^= (int)arg; + key ^= (uintptr_t)arg; bool found = false; Type* res = 0; @@ -1469,6 +1578,29 @@ Jet::Function* Compilation::GetFunction(const std::string& name) return 0; } +Function* Compilation::GetFunction(const std::string& name, const std::vector& args) +{ + //search down the namespace tree for the function + auto next = this->ns; + while (next) + { + auto r = next->members.equal_range(name); + for (auto it = r.first; it != r.second; it++) + { + if (it->second.type == SymbolType::Function) + { + if (it->second.fn->arguments.size() == args.size()) + { + return it->second.fn; + } + } + } + + next = next->parent; + } + return 0; +} + Jet::Symbol Compilation::GetVariableOrFunction(const std::string& name) { //search up the namespace tree for this variable or function @@ -1570,6 +1702,29 @@ void DiagnosticBuilder::Error(const std::string& text, const Token& token) this->diagnostics.push_back(error); } +void DiagnosticBuilder::Error(const std::string& text, const Token& start_token, const Token& end_token) +{ + Diagnostic error; + error.token = start_token; + error.end = end_token; + error.message = text; + + if (start_token.type != TokenType::InvalidToken) + { + auto current_source = start_token.GetSource((Compilation*)compilation); + + error.line = current_source->GetLine(start_token.line); + error.file = current_source->filename; + } + error.severity = 0; + + if (this->callback) + this->callback(error); + + //try and remove exceptions from build system + this->diagnostics.push_back(error); +} + void DiagnosticBuilder::Error(const std::string& text, const std::string& file, int line) { @@ -1587,4 +1742,4 @@ void DiagnosticBuilder::Error(const std::string& text, const std::string& file, //try and remove exceptions from build system this->diagnostics.push_back(error); -} \ No newline at end of file +} diff --git a/Compilation.h b/Compilation.h index 43afd50..de368b5 100644 --- a/Compilation.h +++ b/Compilation.h @@ -20,7 +20,7 @@ namespace llvm } namespace Jet { - std::string exec(const char* cmd); + std::string exec(const char* cmd, int* error_code = 0); struct Diagnostic { @@ -48,6 +48,7 @@ namespace Jet } + void Error(const std::string& text, const Token& start, const Token& end); void Error(const std::string& text, const Token& token); void Error(const std::string& text, const std::string& file, int line = -1); @@ -133,7 +134,7 @@ namespace Jet void AdvanceTypeLookup(Type** dest, const std::string& name, Token* location); - Type* LookupType(const std::string& name, bool load = true, bool error = true); + Type* LookupType(const std::string& name, bool load = true, bool error = true, int start_index = 0); Type* TryLookupType(const std::string& name); //Give size of zero for non-array @@ -147,6 +148,7 @@ namespace Jet } void Error(const std::string& string, Token token); + void Error(const std::string& string, const Token& start, const Token& end); //generates and outputs an exe or lib file void Assemble(const std::string& target = "", const std::string& linker = "", int olevel = 0, bool time = false, bool output_ir = false); @@ -169,10 +171,7 @@ namespace Jet return this->GetFunction(name); } - Function* GetFunction(const std::string& name, const std::vector& args) - { - return this->GetFunction(name); - } + Function* GetFunction(const std::string& name, const std::vector& args); Function* GetFunction(const std::string& name); @@ -191,8 +190,9 @@ namespace Jet module->dump(); } - void SetTarget(const std::string& triple);//make this customizable later + // returns the target used + std::string SetTarget(const std::string& triple);//make this customizable later }; } -#endif \ No newline at end of file +#endif diff --git a/Compiler.cpp b/Compiler.cpp index 2de9db8..ec02aa5 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -22,14 +22,18 @@ using namespace Jet; #ifdef _WIN32 #include - +#include #include #else #include #include + +void Sleep(int duration) +{ + usleep(duration*1000); +} #endif -#include #include //this adds all the available options to the parser for jet @@ -60,11 +64,22 @@ void CompilerOptions::ApplyOptions(OptionParser* parser) void Jet::Diagnostic::Print() { +#ifndef _WIN32 + const char* m_type = "\x1B[31merror\x1B[0m"; +#else + const char* m_type = "error"; +#endif if (token.type != TokenType::InvalidToken) { unsigned int startrow = token.column; unsigned int endrow = token.column + token.text.length(); + // Handle an end token + if (end.type != TokenType::InvalidToken) + { + endrow = end.column + end.text.length(); + } + std::string code = this->line; std::string underline = ""; for (unsigned int i = 0; i < code.length(); i++) @@ -76,12 +91,14 @@ void Jet::Diagnostic::Print() else underline += ' '; } - printf("[error] %s %d:%d to %d:%d: %s\n[error] >>>%s\n[error] >>>%s\n\n", this->file.c_str(), token.line, startrow, token.line, endrow, message.c_str(), code.c_str(), underline.c_str()); + printf("[%s] %s %d:%d to %d:%d: %s\n", m_type, this->file.c_str(), token.line, startrow, token.line, endrow, message.c_str()); + printf("[%s] >>>%s\n", m_type, code.c_str()); + printf("[%s] >>>%s\n\n", m_type, underline.c_str()); } else { //just print something out, it was probably a build system error, not one that occurred in the code - printf("[error] %s: %s\n", this->file.c_str(), message.c_str()); + printf("[%s] %s: %s\n", m_type, this->file.c_str(), message.c_str()); } } @@ -154,12 +171,9 @@ void ExecuteProject(JetProject* project, const char* projectdir) }); x.detach(); #else - // todo run for linux - printf("WARNING: Running your program from the compiler is not yet supported in linux."); + std::string cmd = "gnome-terminal -- build/" + project->project_name; + system(cmd.c_str()); #endif - //system(path.c_str()); - - //spawnl(P_NOWAIT, "cmd.exe", "cmd.exe", path.c_str(), 0); } extern std::string executable_path; @@ -413,63 +427,61 @@ int Compiler::Compile(const char* projectdir, CompilerOptions* optons, const std } else if (compilation->GetErrors().size() > 0) { - printf("Compiling Failed: %d Errors Found\n", compilation->GetErrors().size()); + printf("Compiling Failed: %zi Errors Found\n", compilation->GetErrors().size()); //restore working directory chdir(olddir); return 0; } - else + + compilation->Assemble(options.target, options.linker, options.optimization, options.time, options.output_ir); + + if (compilation->GetErrors().size() > 0) { - compilation->Assemble(options.target, options.linker, options.optimization, options.time, options.output_ir); + goto error; + } - //output build times - std::ofstream rebuild("build/rebuild.txt"); - //output compiler version - rebuild.write(__TIME__, strlen(__TIME__)); - rebuild.write("\n", 1); - for (auto ii : modifiedtimes) - { - char str[150]; + //output build times + std::ofstream rebuild_out("build/rebuild.txt"); + //output compiler version + rebuild_out.write(__TIME__, strlen(__TIME__)); + rebuild_out.write("\n", 1); + for (auto ii : modifiedtimes) + { + char str[150]; #if 0 //_WIN32 - int len = sprintf(str, "%i,%i\n", ii.first, ii.second); + int len = sprintf(str, "%i,%i\n", ii.first, ii.second); #else - int len = sprintf(str, "%li\n", ii); + int len = sprintf(str, "%li\n", ii); #endif - rebuild.write(str, len); - } - //todo: output for dependencies too - - printf("Project built successfully.\n\n"); + rebuild_out.write(str, len); + } - //running postbuild - if (configuration.postbuild.length() > 0) - printf("%s", exec(configuration.postbuild.c_str()).c_str()); + printf("Project built successfully.\n\n"); - //ok now lets add it to the project cache, lets be sure to always save a backup though and need to get current path of the jetc - if (executable_path.length()) - { - this->UpdateProjectList(project.get()); - } + //running postbuild + if (configuration.postbuild.length() > 0) + printf("%s", exec(configuration.postbuild.c_str()).c_str()); - if (options.run && project->IsExecutable()) - { - ExecuteProject(project.get(), projectdir); - Sleep(50);//give it a moment to run, for some reason derps up without this - } - else if (options.run) - { - printf("Warning: Ignoring run option because program is not executable.\n"); - } + //ok now lets add it to the project cache, lets be sure to always save a backup though and need to get current path of the jetc + if (executable_path.length()) + { + this->UpdateProjectList(project.get()); + } - //restore working directory - chdir(olddir); - return 2; + if (options.run && project->IsExecutable()) + { + ExecuteProject(project.get(), projectdir); + Sleep(50);//give it a moment to run, for some reason derps up without this + } + else if (options.run) + { + printf("Warning: Ignoring run option because program is not executable.\n"); } //restore working directory chdir(olddir); - return 1; + return 2; } std::string GetProjectDatabasePath() @@ -589,4 +601,4 @@ void Compiler::UpdateProjectList(JetProject* project) file << project->project_name << "|" << curpath << '|' << project->version << '\n'; } -} \ No newline at end of file +} diff --git a/CompilerContext.cpp b/CompilerContext.cpp index f5980b7..e7180ff 100644 --- a/CompilerContext.cpp +++ b/CompilerContext.cpp @@ -16,52 +16,17 @@ using namespace Jet; -CompilerContext* CompilerContext::AddFunction(const std::string& fname, Type* ret, const std::vector>& args, Type* member, bool lambda) +CompilerContext* CompilerContext::StartFunctionDefinition(Function* func) { - Function* func = 0; - if (member) - { - //ok, if member just pass the type so we dont have to do this crap - int i = member->name.length() + 2; - std::string fname2 = fname.substr(++i, fname.length() - i); - - auto range = member->data->functions.equal_range(fname2); - for (auto ii = range.first; ii != range.second; ii++) - { - //printf("found option for %s with %i args\n", fname.c_str(), ii->second->argst.size()); - if (ii->second->arguments.size() == args.size()) - { - func = ii->second; - } - } - } - else - { - func = root->ns->GetFunction(fname); - if (!func) - { - //no function exists, create it - func = new Function(fname, lambda); - func->return_type = ret; - func->arguments = args; - - if (member == false) - this->root->ns->members.insert({ fname, func }); - } - } - - func->Load(this->root); - auto n = new CompilerContext(this->root, this); n->function = func; func->context = n; + + func->Load(this->root); + llvm::BasicBlock *bb = llvm::BasicBlock::Create(root->context, "entry", n->function->f); root->builder.SetInsertPoint(bb); - // Do not export lambdas - if (lambda) - func->do_export = false; - return n; } @@ -89,16 +54,30 @@ CValue CompilerContext::UnaryOperation(TokenType operation, CValue value) return CValue(value.type, res); } - else if (value.type->IsInteger())//value.type->type == Types::Int || value.type->type == Types::Short || value.type->type == Types::Char) + else if (value.type->IsInteger()) { - //integer probably + const auto& type = value.type->type; switch (operation) { case TokenType::Increment: - res = root->builder.CreateAdd(value.val, root->builder.getInt32(1)); + if (type == Types::Int || type == Types::UInt) + res = root->builder.CreateAdd(value.val, root->builder.getInt32(1)); + else if (type == Types::Short || type == Types::UShort) + res = root->builder.CreateAdd(value.val, root->builder.getInt16(1)); + else if (type == Types::Char || type == Types::UChar) + res = root->builder.CreateAdd(value.val, root->builder.getInt8(1)); + else if (type == Types::Long || type == Types::ULong) + res = root->builder.CreateAdd(value.val, root->builder.getInt64(1)); break; case TokenType::Decrement: - res = root->builder.CreateSub(value.val, root->builder.getInt32(1)); + if (type == Types::Int || type == Types::UInt) + res = root->builder.CreateSub(value.val, root->builder.getInt32(1)); + else if (type == Types::Short || type == Types::UShort) + res = root->builder.CreateSub(value.val, root->builder.getInt16(1)); + else if (type == Types::Char || type == Types::UChar) + res = root->builder.CreateSub(value.val, root->builder.getInt8(1)); + else if (type == Types::Long || type == Types::ULong) + res = root->builder.CreateSub(value.val, root->builder.getInt64(1)); break; case TokenType::Minus: res = root->builder.CreateNeg(value.val); @@ -126,7 +105,6 @@ CValue CompilerContext::UnaryOperation(TokenType operation, CValue value) default: this->root->Error("Invalid Unary Operation '" + TokenToString[operation] + "' On Type '" + value.type->base->ToString() + "'", *current_token); } - } else if (value.type->type == Types::Bool) { @@ -143,7 +121,7 @@ CValue CompilerContext::UnaryOperation(TokenType operation, CValue value) void CompilerContext::Store(CValue loc, CValue val, bool RVO) { - if (loc.type->base->type == Types::Struct && RVO == false) + if (loc.type->base->type == Types::Struct && RVO == false && val.type->type == Types::Struct && loc.type->base == val.type) { if (loc.type->base->data->is_class == true) this->root->Error("Cannot copy class '" + loc.type->base->data->name + "' unless it has a copy operator.", *this->current_token); @@ -192,7 +170,7 @@ void CompilerContext::Store(CValue loc, CValue val, bool RVO) } auto dptr = root->builder.CreatePointerCast(loc.val, root->CharPointerType->GetLLVMType()); auto sptr = root->builder.CreatePointerCast(vall.pointer, root->CharPointerType->GetLLVMType()); - root->builder.CreateMemCpy(dptr, sptr, loc.type->base->GetSize(), 1); + root->builder.CreateMemCpy(dptr, 0, sptr, 0, loc.type->base->GetSize());// todo properly handle alignment return; } else if (loc.type->base->type == Types::InternalArray) @@ -201,7 +179,7 @@ void CompilerContext::Store(CValue loc, CValue val, bool RVO) I->eraseFromParent();// remove the load so we dont freak out llvm doing a struct copy auto dptr = root->builder.CreatePointerCast(loc.val, root->CharPointerType->GetLLVMType()); auto sptr = root->builder.CreatePointerCast(vall.pointer, root->CharPointerType->GetLLVMType()); - root->builder.CreateMemCpy(dptr, sptr, loc.type->base->GetSize(), 1); + root->builder.CreateMemCpy(dptr, 0, sptr, 0, loc.type->base->GetSize());// todo properly handle alignment return; } @@ -395,9 +373,11 @@ CValue CompilerContext::BinaryOperation(Jet::TokenType op, CValue left, CValue l case TokenType::XorAssign: res = root->builder.CreateXor(left.val, right.val); break; + case TokenType::ShlAssign: case TokenType::LeftShift: res = root->builder.CreateShl(left.val, right.val); break; + case TokenType::ShrAssign: case TokenType::RightShift: res = root->builder.CreateLShr(left.val, right.val); break; @@ -435,7 +415,7 @@ Function* CompilerContext::GetMethod(const std::string& name, const std::vector< if (Struct == 0) { //global function? - auto iter = this->root->GetFunction(name); + auto iter = this->root->GetFunction(name, args); if (iter == 0) { //check if its a type, if so try and find a constructor @@ -597,7 +577,9 @@ CValue CompilerContext::Call(const std::string& name, const std::vector& { std::vector arsgs; for (auto ii : args) + { arsgs.push_back(ii.type); + } auto old_tok = this->current_token; Function* fun = this->GetMethod(name, arsgs, Struct); @@ -765,7 +747,7 @@ void CompilerContext::SetDebugLocation(const Token& t) this->root->builder.SetCurrentDebugLocation(llvm::DebugLoc::get(t.line, t.column, this->function->scope)); } -CValue CompilerContext::GetVariable(const std::string& name) +CValue CompilerContext::GetVariable(const std::string& name, bool* is_const) { auto cur = this->scope; CValue value; @@ -774,7 +756,11 @@ CValue CompilerContext::GetVariable(const std::string& name) auto iter = cur->named_values.find(name); if (iter != cur->named_values.end()) { - value = iter->second; + value = iter->second.value; + if (is_const) + { + *is_const = iter->second.is_const; + } break; } cur = cur->prev; @@ -782,6 +768,10 @@ CValue CompilerContext::GetVariable(const std::string& name) if (value.type->type == Types::Void) { + if (is_const) + { + *is_const = false; + } auto sym = this->root->GetVariableOrFunction(name); if (sym.type != SymbolType::Invalid) { @@ -859,6 +849,12 @@ llvm::ReturnInst* CompilerContext::Return(CValue ret) if (ret.type->type == Types::Void) { + // Only allow this if the function return type is void + if (this->function->return_type->type != Types::Void) + { + this->root->Error("Cannot return void in function returning '" + + this->function->return_type->ToString() + "'!", *current_token); + } return root->builder.CreateRetVoid(); } else if (ret.type->type == Types::Struct) @@ -869,7 +865,7 @@ llvm::ReturnInst* CompilerContext::Return(CValue ret) //do a memcpy auto dptr = root->builder.CreatePointerCast(this->function->f->arg_begin(), this->root->CharPointerType->GetLLVMType()); auto sptr = root->builder.CreatePointerCast(ret.pointer, this->root->CharPointerType->GetLLVMType()); - root->builder.CreateMemCpy(dptr, sptr, ret.type->GetSize(), 1); + root->builder.CreateMemCpy(dptr, 0, sptr, 0, ret.type->GetSize());// todo properly handle alignment return root->builder.CreateRetVoid(); } @@ -912,21 +908,41 @@ CValue CompilerContext::DoCast(Type* t, CValue value, bool Explicit) if (t->type == Types::Double || t->type == Types::Float) { if (value.type->IsSignedInteger()) + { return CValue(t, root->builder.CreateSIToFP(value.val, tt)); + } else + { return CValue(t, root->builder.CreateUIToFP(value.val, tt)); + } } if (t->type == Types::Bool) + { return CValue(t, root->builder.CreateIsNotNull(value.val)); + } if (t->type == Types::Pointer) { llvm::ConstantInt* ty = llvm::dyn_cast(value.val); if (Explicit == false && (ty == 0 || ty->getSExtValue() != 0)) + { root->Error("Cannot cast a non-zero integer value to pointer implicitly.", *this->current_token); + } return CValue(t, root->builder.CreateIntToPtr(value.val, t->GetLLVMType())); } + // This turned out to be hard.... + /*// Disallow implicit casts to smaller types + if (!Explicit && t->GetSize() < value.type->GetSize()) + { + // for now just ignore literals + llvm::ConstantInt* is_literal = llvm::dyn_cast(value.val); + if (!is_literal) + { + root->Error("Cannot implicitly cast from '" + value.type->ToString() + "' to a smaller integer type: '" + t->ToString() + "'.", *this->current_token); + } + }*/ + if (t->IsSignedInteger()) return CValue(t, root->builder.CreateSExtOrTrunc(value.val, tt)); else if (t->IsInteger()) @@ -1013,7 +1029,7 @@ CValue CompilerContext::DoCast(Type* t, CValue value, bool Explicit) else if (Explicit && t->type == Types::Function) return CValue(t, this->root->builder.CreateBitOrPointerCast(value.val, tt)); } - if (t->type == Types::Union && value.type->type == Types::Struct) + if (t->type == Types::Union) { for (unsigned int i = 0; i < t->_union->members.size(); i++) { @@ -1174,12 +1190,13 @@ Scope* CompilerContext::PushScope() void Scope::Destruct(CompilerContext* context, llvm::Value* ignore) { - for (auto ii : this->named_values) + for (auto& ii : this->named_values) { - if (ii.second.val == ignore) + auto& value = ii.second.value; + if (value.val == ignore) continue;//dont destruct what we are returning - if (ii.second.type->type == Types::Pointer && ii.second.type->base->type == Types::Struct) - context->Destruct(ii.second, 0); + if (value.type->type == Types::Pointer && value.type->base->type == Types::Struct) + context->Destruct(value, 0); //else if (ii.second.type->type == Types::Pointer && ii.second.type->base->type == Types::Array && ii.second.type->base->base->type == Types::Struct) // context->Destruct(CValue(ii.second.type->base, ii.second.val), context->root->builder.getInt32(ii.second.type->base->size)); } @@ -1367,4 +1384,4 @@ void CompilerContext::Destruct(CValue pointer, llvm::Value* arr_size) this->root->builder.SetInsertPoint(end); } } -} \ No newline at end of file +} diff --git a/CompilerContext.h b/CompilerContext.h index 959a6db..c3955f4 100644 --- a/CompilerContext.h +++ b/CompilerContext.h @@ -24,7 +24,12 @@ namespace Jet { struct Scope { - std::map named_values; + struct NamedValue + { + CValue value; + bool is_const; + }; + std::map named_values; //used for struct arrays std::vector to_destruct; @@ -112,13 +117,13 @@ namespace Jet return CValue(this->root->CharPointerType, res); } - void RegisterLocal(const std::string& name, CValue val, bool needs_destruction = false) + void RegisterLocal(const std::string& name, CValue val, bool needs_destruction = false, bool is_const = false) { if (this->scope->named_values.find(name) != this->scope->named_values.end()) this->root->Error("Variable '" + name + "' already defined", *this->current_token); if (needs_destruction) this->scope->to_destruct.push_back(val); - this->scope->named_values[name] = val; + this->scope->named_values[name] = { val, is_const }; } std::function local_reg_callback; @@ -129,7 +134,7 @@ namespace Jet this->tscope->named_values[name] = ty; } - CValue GetVariable(const std::string& name); + CValue GetVariable(const std::string& name, bool* is_const = 0); Type* TCGetVariable(const std::string& name) { @@ -218,18 +223,17 @@ namespace Jet return value; } - llvm::StoreInst* Store(const std::string& name, CValue val) + void Store(const std::string& name, CValue val) { //for each scope - CValue value = GetVariable(name); + bool is_const = false; + CValue value = GetVariable(name, &is_const); + if (is_const) + { + this->root->Error("Cannot assign to const variable!", *current_token); + } this->Store(value, val); - //return 0; - //val = this->DoCast(value.type->base, val); - - //check if there is an operator - return 0; - //return root->builder.CreateStore(val.val, value.val); } void Store(CValue loc, CValue val, bool rvo = false); @@ -337,7 +341,7 @@ namespace Jet CValue DoCast(Type* t, CValue value, bool Explicit = false); bool CheckCast(Type* src, Type* dest, bool Explicit = false, bool Throw = true); - CompilerContext* AddFunction(const std::string& fname, Type* ret, const std::vector>& args, Type* member, bool lambda); + CompilerContext* StartFunctionDefinition(Function* function); Function* GetMethod(const std::string& name, const std::vector& args, Type* Struct = 0); CValue Call(const std::string& name, const std::vector& args, Type* Struct = 0, bool devirtualize = false); diff --git a/ControlExpressions.cpp b/ControlExpressions.cpp index d63291e..6ff9c5a 100644 --- a/ControlExpressions.cpp +++ b/ControlExpressions.cpp @@ -276,8 +276,10 @@ CValue YieldExpression::Compile(CompilerContext* context) //compile the yielded value auto value = right->Compile(context); + auto dest_type = data.type->base->data->struct_members[1].type; + //store result into the generator context - value = context->DoCast(data.type->base->data->struct_members[1].type, value);//cast to the correct type + value = context->DoCast(dest_type, value);//cast to the correct type br = context->root->builder.CreateGEP(data.val, { context->root->builder.getInt32(0), context->root->builder.getInt32(1) }); context->root->builder.CreateStore(value.val, br); } @@ -355,7 +357,7 @@ CValue MatchExpression::Compile(CompilerContext* context) ii.block->Compile(context); //need to do this without destructing args - context->scope->named_values[ii.name.text] = CValue(); + context->scope->named_values[ii.name.text] = { CValue(), false }; context->PopScope(); //branch to end @@ -390,9 +392,11 @@ CValue CallExpression::Compile(CompilerContext* context) { //im a struct yo fname = index->member.text; - stru = index->GetBaseType(context); - assert(stru->loaded); - llvm::Value* self = index->GetBaseElementPointer(context).val; + //stru = index->GetBaseType(context); + //assert(stru->loaded); + auto left = index->GetBaseElementPointer(context); + stru = left.type->base; + llvm::Value* self = left.val; if (index->token.type == TokenType::Pointy) { if (stru->type != Types::Pointer && stru->type != Types::Array) diff --git a/DeclarationExpressions.cpp b/DeclarationExpressions.cpp index fd2a11b..5196765 100644 --- a/DeclarationExpressions.cpp +++ b/DeclarationExpressions.cpp @@ -81,7 +81,7 @@ Type* FunctionExpression::TypeCheck(CompilerContext* context) if (this->is_generator) { - auto func = context->root->ns->GetFunction(this->GetRealName()); + auto func = myself;// context->root->ns->GetFunction(this->GetRealName()); auto str = func->return_type; //add _context nc->TCRegisterLocal("_context", str->GetPointerType()->GetPointerType()); @@ -111,22 +111,6 @@ Type* FunctionExpression::TypeCheck(CompilerContext* context) return 0; } - -unsigned int uuid = 5; -std::string FunctionExpression::GetRealName() -{ - std::string fname; - if (name.text.length() > 0) - fname = name.text; - else - fname = "_lambda_id_" + std::to_string(uuid++);// Todo fix this returning a different value each time - auto Struct = dynamic_cast(this->parent); - if (this->Struct.text.length() > 0) - return "__" + this->Struct.text + "_" + fname; - else - return Struct ? "__" + Struct->GetName() + "_" + fname : fname; -} - CValue FunctionExpression::Compile(CompilerContext* context) { auto Struct = dynamic_cast(this->parent) ? dynamic_cast(this->parent)->GetName() : this->Struct.text; @@ -180,7 +164,7 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) //add the context pointer as an argument if this is a generator if (this->is_generator) { - auto func = context->root->ns->GetFunction(this->GetRealName()); + auto func = myself;// context->root->ns->GetFunction(this->GetRealName()); auto str = func->return_type; str->Load(context->root); @@ -251,8 +235,11 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) } } - for (auto ii : *this->args) + for (auto& ii : *this->args) + { + context->CurrentToken(&ii.type); argsv.push_back({ context->root->LookupType(ii.type.text), ii.name.text }); + } context->CurrentToken(&this->ret_type); @@ -271,7 +258,7 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) { //allocate the function object std::vector args; - for (auto ii : argsv) + for (auto& ii : argsv) args.push_back(ii.first); lambda_type = context->root->LookupType("function<" + context->root->GetFunctionType(ret, args)->ToString() + ">"); @@ -295,12 +282,23 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) } else { - function_context = context->AddFunction(this->GetRealName(), ret, argsv, struct_name.length() > 0 ? argsv[0].first->base : 0, is_lambda);// , this->varargs); + // create the function if this was a lambda + if (this->name.text.length() == 0) + { + myself = new Function(this->GetFunctionNamePrefix(), false); + myself->expression = this; + myself->is_virtual = false; + myself->arguments = argsv; + myself->return_type = ret; + context->root->functions.push_back(myself); + } + + function_context = context->StartFunctionDefinition(myself);//this->GetFunctionNamePrefix(), ret, argsv, struct_name.length() > 0 ? argsv[0].first->base : 0, is_lambda, myself); } function_context->function->lambda.storage_type = storage_t; context->root->current_function = function_context; - function_context->function->Load(context->root); + //function_context->function->Load(context->root); function_context->SetDebugLocation(this->token); @@ -352,7 +350,7 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) //add arguments int i = 0; - for (auto ii : *this->args) + for (auto& ii : *this->args) { auto ptr = data.val; auto val = function_context->root->builder.CreateGEP(ptr, { function_context->root->builder.getInt32(0), function_context->root->builder.getInt32(2 + i++) }); @@ -416,13 +414,15 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) if (this->is_generator) { + context->root->builder.SetCurrentDebugLocation(0); + //compile the other function necessary for an iterator - auto func = context->AddFunction(this->GetRealName(), 0, { argsv.front() }, struct_name.length() > 0 ? argsv[0].first : 0, is_lambda); + auto func = context->StartFunctionDefinition(myself);//this->GetFunctionNamePrefix(), 0, { argsv.front() }, struct_name.length() > 0 ? argsv[0].first : 0, is_lambda, myself); auto str = func->function->return_type; context->root->current_function = func; - func->function->Load(context->root); + //func->function->Load(context->root);// this shouldnt be necessary, Add Function loads it //alloca the new context auto alloc = context->root->builder.CreateAlloca(str->GetLLVMType()); @@ -448,7 +448,7 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) //then return the newly created iterator object by storing it into the first arg auto sptr = context->root->builder.CreatePointerCast(alloc, context->root->CharPointerType->GetLLVMType()); auto dptr = context->root->builder.CreatePointerCast(func->function->f->arg_begin(), context->root->CharPointerType->GetLLVMType()); - context->root->builder.CreateMemCpy(dptr, sptr, str->GetSize(), 1); + context->root->builder.CreateMemCpy(dptr, 0, sptr, 0, str->GetSize());// todo properly handle alignment context->root->builder.CreateRetVoid(); @@ -507,20 +507,43 @@ CValue FunctionExpression::DoCompile(CompilerContext* context) return CValue(function_context->function->GetType(context->root), function_context->function->f); } +std::string FunctionExpression::GetFunctionNamePrefix() +{ + std::string fname; + if (name.text.length() > 0) + fname = name.text; + else + fname = "_lambda_"; + + auto str = dynamic_cast(this->parent) ? dynamic_cast(this->parent)->GetName() : this->Struct.text; + + const auto& ns = this->GetNamespaceQualifier(); + if (str.length()) + fname = str + "_" + fname; + if (ns.length() > 0) + return ns + "_" + fname; + return fname; +} + void FunctionExpression::CompileDeclarations(CompilerContext* context) { context->CurrentToken(&this->token); - std::string fname = name.text; if (name.text.length() == 0) - return;//dont compile expression for lambdas + { + return;//dont compile declaration for lambdas + } + + std::string name_prefix = this->GetFunctionNamePrefix(); bool advlookup = true; - Function* fun = new Function(this->GetRealName(), false); + auto str = dynamic_cast(this->parent) ? dynamic_cast(this->parent)->GetName() : this->Struct.text; + + Function* fun = new Function(name_prefix, false); fun->expression = this; fun->is_virtual = (this->token.type == TokenType::Virtual); context->root->functions.push_back(fun); - auto str = dynamic_cast(this->parent) ? dynamic_cast(this->parent)->GetName() : this->Struct.text; + myself = fun; if (auto attr = dynamic_cast(this->parent)) { @@ -534,6 +557,7 @@ void FunctionExpression::CompileDeclarations(CompilerContext* context) } bool is_trait = false; + const auto& fname = name.text; if (str.length() > 0) { auto type = context->root->LookupType(str, false); @@ -559,7 +583,7 @@ void FunctionExpression::CompileDeclarations(CompilerContext* context) { //build data about the generator context struct Type* str = new Type; - str->name = this->GetRealName() + "_yielder_context"; + str->name = name_prefix + "_yielder_context"; str->type = Types::Struct; str->data = new Jet::Struct; str->data->name = str->name; @@ -570,11 +594,12 @@ void FunctionExpression::CompileDeclarations(CompilerContext* context) //add default iterator methods, will fill in function later { - auto func = new Function(this->GetRealName() + "_generator", name.text.length() == 0); + auto func = new Function(name_prefix + "_generator", name.text.length() == 0); func->return_type = context->root->BoolType; func->arguments = { { 0, "_context" } }; func->arguments.resize(1); context->root->AdvanceTypeLookup(&func->arguments[0].first, str->name + "*", &this->ret_type); + context->root->functions.push_back(func); auto n = new CompilerContext(context->root, context); n->function = func; @@ -584,11 +609,12 @@ void FunctionExpression::CompileDeclarations(CompilerContext* context) str->data->functions.insert({ "MoveNext", func }); } { - auto func = new Function(this->GetRealName() + "_yield_reset", name.text.length() == 0); + auto func = new Function(name_prefix + "_yield_reset", name.text.length() == 0); func->return_type = &VoidType; func->arguments = { { 0, "_context" } }; func->arguments.resize(1); context->root->AdvanceTypeLookup(&func->arguments[0].first, str->name + "*", &this->ret_type); + context->root->functions.push_back(func); auto n = new CompilerContext(context->root, context); n->function = func; @@ -598,9 +624,10 @@ void FunctionExpression::CompileDeclarations(CompilerContext* context) str->data->functions.insert({ "Reset", func }); } { - auto func = new Function(this->GetRealName() + "_generator_current", name.text.length() == 0); + auto func = new Function(name_prefix + "_generator_current", name.text.length() == 0); func->return_type = &VoidType; context->root->AdvanceTypeLookup(&func->return_type, this->ret_type.text, &this->ret_type); + context->root->functions.push_back(func); func->arguments = { { 0, "_context" } }; func->arguments.resize(1); @@ -700,7 +727,10 @@ void ExternExpression::CompileDeclarations(CompilerContext* context) { std::string fname = name.text; - Function* fun = new Function(fname, false); + // todo come up with a better way to handle c externs + bool is_c = (token.text == "extern_c"); + + Function* fun = new Function(fname, false, is_c); if (auto attr = dynamic_cast(this->parent)) { @@ -721,6 +751,7 @@ void ExternExpression::CompileDeclarations(CompilerContext* context) fun->f = 0; if (Struct.length() > 0) { + // todo this seems wrong fun->name = "__" + Struct + "_" + fname;//mangled name //add to struct @@ -756,12 +787,22 @@ void ExternExpression::CompileDeclarations(CompilerContext* context) CValue LetExpression::Compile(CompilerContext* context) { - context->CurrentToken(&(*_names)[0].second); + context->CurrentToken(&(*_names)[0].name); // If im in global scope, add a global variable if (this->parent->parent == 0) { - auto type = context->root->LookupType(this->_names->front().first.text); + if (this->_names->front().type.text.length() == 0) + { + context->root->Error("Cannot infer type for a global variable", token); + } + + auto type = context->root->LookupType(this->_names->front().type.text); + + if (is_const) + { + context->root->Error("Const global variables are not yet supported", token); + } //should I add a constructor? llvm::Constant* cval = 0; @@ -773,15 +814,15 @@ CValue LetExpression::Compile(CompilerContext* context) context->root->Error("Cannot instantiate global with non constant value", token); } - if (this->_names->front().first.text.back() == ']') + if (this->_names->front().type.text.back() == ']') { - std::string len = this->_names->front().first.text; + std::string len = this->_names->front().type.text; len = len.substr(len.find_first_of('[') + 1); - context->root->AddGlobal(this->_names->front().second.text, type->base, std::atoi(len.c_str())); + context->root->AddGlobal(this->_names->front().name.text, type->base, std::atoi(len.c_str())); } else { - context->root->AddGlobal(this->_names->front().second.text, type, 0, cval); + context->root->AddGlobal(this->_names->front().name.text, type, 0, cval); } return CValue(); @@ -790,16 +831,16 @@ CValue LetExpression::Compile(CompilerContext* context) bool needs_destruction = false; int i = 0; for (auto ii : *this->_names) { - auto aname = ii.second.text; + auto aname = ii.name.text; Type* type = 0; CValue val; llvm::AllocaInst* Alloca = 0; - if (ii.first.text.length()) + if (ii.type.text.length()) { - context->CurrentToken(&ii.first); - type = context->root->LookupType(ii.first.text); - context->CurrentToken(&(*_names)[0].second); + context->CurrentToken(&ii.type); + type = context->root->LookupType(ii.type.text); + context->CurrentToken(&(*_names)[0].name); if (this->_right) val = (*this->_right)[i++].second->Compile(context); } @@ -824,34 +865,37 @@ CValue LetExpression::Compile(CompilerContext* context) //output debug info llvm::DIFile* unit = context->root->debug_info.file; type->Load(context->root); - llvm::DILocalVariable* D = context->root->debug->createAutoVariable(context->function->scope, aname, unit, ii.second.line, + llvm::DILocalVariable* D = context->root->debug->createAutoVariable(context->function->scope, aname, unit, ii.name.line, type->GetDebugType(context->root)); llvm::Instruction *Call = context->root->debug->insertDeclare( var_ptr, D, context->root->debug->createExpression(), llvm::DebugLoc::get(this->token.line, this->token.column, context->function->scope), context->root->builder.GetInsertBlock()); - Call->setDebugLoc(llvm::DebugLoc::get(ii.second.line, ii.second.column, context->function->scope)); + Call->setDebugLoc(llvm::DebugLoc::get(ii.name.line, ii.name.column, context->function->scope)); //still need to do store - context->RegisterLocal(aname, CValue(type->GetPointerType(), var_ptr)); + // todo this probably needs to support things with destructors.. + context->RegisterLocal(aname, CValue(type->GetPointerType(), var_ptr), false, is_const); continue; } - else if (ii.first.text.length() > 0)//type was specified + else if (ii.type.text.length() > 0)//type was specified { - context->CurrentToken(&ii.first); + context->CurrentToken(&ii.type); - type = context->root->LookupType(ii.first.text); + type = context->root->LookupType(ii.type.text); auto TheFunction = context->function->f; llvm::IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); if (type->type == Types::Struct && type->data->templates.size() > 0) - context->root->Error("Missing template arguments for type '" + type->ToString() + "'", ii.first); + { + context->root->Error("Missing template arguments for type '" + type->ToString() + "'", ii.type); + } else if (type->type == Types::InternalArray) { if (this->_right) { - context->root->Error("Cannot assign to a sized array type!", ii.second); + context->root->Error("Cannot assign to a sized array type!", ii.name); } needs_destruction = true; @@ -882,7 +926,7 @@ CValue LetExpression::Compile(CompilerContext* context) } else if (type->GetBaseType()->type == Types::Trait) { - context->root->Error("Cannot instantiate trait", ii.second); + context->root->Error("Cannot instantiate trait", ii.name); } else { @@ -920,20 +964,20 @@ CValue LetExpression::Compile(CompilerContext* context) } else { - context->root->Error("Cannot infer variable type without a value!", ii.second); + context->root->Error("Cannot infer variable type without a value!", ii.name); } // Add debug info llvm::DIFile* unit = context->root->debug_info.file; type->Load(context->root); - llvm::DILocalVariable* D = context->root->debug->createAutoVariable(context->function->scope, aname, unit, ii.second.line, + llvm::DILocalVariable* D = context->root->debug->createAutoVariable(context->function->scope, aname, unit, ii.name.line, type->GetDebugType(context->root)); llvm::Instruction *declare = context->root->debug->insertDeclare( Alloca, D, context->root->debug->createExpression(), llvm::DebugLoc::get(this->token.line, this->token.column, context->function->scope), context->root->builder.GetInsertBlock()); - declare->setDebugLoc(llvm::DebugLoc::get(ii.second.line, ii.second.column, context->function->scope)); + declare->setDebugLoc(llvm::DebugLoc::get(ii.name.line, ii.name.column, context->function->scope)); - context->RegisterLocal(aname, CValue(type->GetPointerType(), Alloca), needs_destruction); + context->RegisterLocal(aname, CValue(type->GetPointerType(), Alloca), needs_destruction, is_const); //construct it! if (this->_right == 0) @@ -1095,13 +1139,18 @@ void StructExpression::AddConstructors(CompilerContext* context) auto ret = &VoidType; - CompilerContext* function = context->AddFunction(ii.second->name, ret, argsv, Struct.length() > 0 ? str : 0, false);// , this->varargs); + //no function exists, create it + auto func = new Function(ii.second->name, false); + func->return_type = ret; + func->arguments = argsv; + + CompilerContext* function = context->StartFunctionDefinition(func); ii.second->f = function->function->f; context->root->current_function = function; - function->function->context = function; - function->function->Load(context->root); + //function->function->context = function; + //function->function->Load(context->root); function->SetDebugLocation(this->token); //alloc args @@ -1176,13 +1225,17 @@ void StructExpression::AddConstructors(CompilerContext* context) auto ret = &VoidType; - CompilerContext* function = context->AddFunction(ii.second->name, ret, argsv, Struct.length() > 0 ? str : 0, false);// , this->varargs); + auto func = new Function(ii.second->name, false); + func->return_type = ret; + func->arguments = argsv; + + CompilerContext* function = context->StartFunctionDefinition(func); ii.second->f = function->function->f; context->root->current_function = function; - function->function->context = function; - function->function->Load(context->root); + //function->function->context = function; + //function->function->Load(context->root); function->SetDebugLocation(this->token); //alloc args @@ -1373,14 +1426,21 @@ void StructExpression::AddConstructors(CompilerContext* context) void StructExpression::CompileDeclarations(CompilerContext* context) { //build data about the struct - Type* str = new Type(this->name.text, Types::Struct, new Struct); + std::string type_name; + const auto& ns = context->root->ns->GetQualifiedName(); + if (ns.length() > 0) + type_name = ns + "::" + this->name.text; + else + type_name = this->name.text; + + Type* str = new Type(type_name, Types::Struct, new Struct); if (this->token.type == TokenType::Class) str->data->is_class = true; context->root->ns->members.insert({ this->name.text, str }); str->ns = context->root->ns; - str->data->name = this->name.text; + str->data->name = type_name; str->data->expression = this; if (this->base_type.text.length()) context->root->AdvanceTypeLookup(&str->data->parent_struct, this->base_type.text, &this->base_type); @@ -1438,7 +1498,7 @@ void StructExpression::CompileDeclarations(CompilerContext* context) else { //this is just for templated structs for typechecking - auto func = new Function(ii.function->GetRealName(), false); + auto func = new Function(ii.function->GetFunctionNamePrefix(), false); context->root->typecheck = true; context->root->AdvanceTypeLookup(&func->return_type, ii.function->ret_type.text, &ii.function->ret_type); func->arguments.push_back({ 0, "this" }); diff --git a/DeclarationExpressions.h b/DeclarationExpressions.h index 892340d..196f28f 100644 --- a/DeclarationExpressions.h +++ b/DeclarationExpressions.h @@ -19,16 +19,28 @@ namespace Jet class LetExpression : public Expression { + bool is_const; Token token, equals; - std::vector>* _names; + + public: + struct TypeNamePair + { + Token type; + Token name; + }; + + private: + std::vector* _names; std::vector>* _right; public: - LetExpression(Token token, Token equals, std::vector>* names, std::vector>* right) + LetExpression(Token token, Token equals, std::vector* names, std::vector>* right) { this->equals = equals; this->token = token; this->_names = names; this->_right = right; + + is_const = (token.type == TokenType::Const); } ~LetExpression() @@ -57,15 +69,18 @@ namespace Jet { //register the local int i = 0; - for (auto ii : *this->_names) + for (auto& ii : *this->_names) { - if (ii.first.text.length()) - context->TCRegisterLocal(ii.second.text, context->root->LookupType(ii.first.text, false)->GetPointerType()); + if (ii.type.text.length()) + { + context->CurrentToken(&ii.type); + context->TCRegisterLocal(ii.name.text, context->root->LookupType(ii.type.text, false)->GetPointerType()); + } else { //type inference auto ty = (*this->_right)[i].second->TypeCheck(context); - context->TCRegisterLocal(ii.second.text, ty->GetPointerType()); + context->TCRegisterLocal(ii.name.text, ty->GetPointerType()); } i++; } @@ -80,9 +95,9 @@ namespace Jet for (auto ii : *_names) { - if (ii.first.text.length() > 0) - ii.first.Print(output, source); - ii.second.Print(output, source); + if (ii.type.text.length() > 0) + ii.type.Print(output, source); + ii.name.Print(output, source); } if (this->_right) @@ -178,7 +193,6 @@ namespace Jet class NamespaceExpression : public Expression { - Token name; Token token; BlockExpression* block; std::vector>* names; @@ -256,6 +270,26 @@ namespace Jet { visitor->Visit(this); } + + // returns the namespace that we create, if any + std::string namespaceprefix_; + virtual const char* GetNamespace() + { + if (namespaceprefix_.length()) + { + return namespaceprefix_.c_str(); + } + + for (int i = 0; i < names->size(); i++) + { + namespaceprefix_ += (*names)[i].first.text; + if (i != names->size() - 1) + { + namespaceprefix_ += "__"; + } + } + return namespaceprefix_.c_str(); + } }; struct FunctionArg @@ -286,6 +320,8 @@ namespace Jet std::vector>* templates; Token open_bracket, close_bracket; Token oper; + + Function* myself; public: ScopeExpression* GetBlock() @@ -319,9 +355,9 @@ namespace Jet delete captures; } - std::string GetRealName(); + std::string GetFunctionNamePrefix(); - std::string GetName() + const std::string& GetName() { return this->name.text; } @@ -708,6 +744,15 @@ namespace Jet ii.definition->Visit(visitor); } } + + // returns the namespace that we create, if any + std::string namespaceprefix_; + virtual const char* GetNamespace() + { + namespaceprefix_ = "_"; + namespaceprefix_ += this->name.text; + return namespaceprefix_.c_str(); + } }; class AttributeExpression : public Expression diff --git a/Expressions.cpp b/Expressions.cpp index bb940ed..00eb103 100644 --- a/Expressions.cpp +++ b/Expressions.cpp @@ -34,6 +34,31 @@ CValue GetPtrToExprValue(CompilerContext* context, Expression* right) context->root->Error("Not Implemented", *context->current_token); } +const std::string& Expression::GetNamespaceQualifier() +{ + if (qualified_namespace_.length()) + { + return qualified_namespace_; + } + + // go down the tree and build up a qualified namespace + if (!this->parent) + { + return qualified_namespace_;//no parent, no problem + } + + qualified_namespace_ = this->parent->GetNamespaceQualifier(); + + const char* ns = GetNamespace(); + if (ns) + { + qualified_namespace_ += "__"; + qualified_namespace_ += ns; + } + + return qualified_namespace_; +} + CValue PrefixExpression::Compile(CompilerContext* context) { context->CurrentToken(&this->_operator); @@ -127,7 +152,7 @@ Type* IndexExpression::GetBaseType(Compilation* compiler) { auto res = curscope->named_values.find(p->GetName()); if (res != curscope->named_values.end()) - return res->second.type; + return res->second.value.type; } while (curscope = curscope->prev); break; } @@ -153,11 +178,19 @@ CValue IndexExpression::GetBaseElementPointer(CompilerContext* context) } else if (auto call = dynamic_cast(left)) { - //store the value then return the pointer to it + //return a modifiable pointer to the value auto val = call->Compile(context); - auto alloca = context->root->builder.CreateAlloca(val.type->GetLLVMType()); - - return CValue(val.type->GetPointerType(), alloca); + if (val.pointer) + { + return CValue(val.type->GetPointerType(), val.pointer); + } + else + { + // need to copy it in this case + auto alloca = context->root->builder.CreateAlloca(val.type->GetLLVMType()); + context->root->builder.CreateStore(val.val, alloca); + return CValue(val.type->GetPointerType(), alloca); + } } context->root->Error("Could not handle Get Base Element Pointer", token); } @@ -294,7 +327,7 @@ CValue GetStructElement(CompilerContext* context, const std::string& name, const return CValue(type->data->struct_members[index].type->GetPointerType(), loc); } -CValue IndexExpression::GetElementPointer(CompilerContext* context) +CValue IndexExpression::GetElementPointer(CompilerContext* context, bool for_store) { auto p = dynamic_cast(left); auto i = dynamic_cast(left); @@ -323,7 +356,7 @@ CValue IndexExpression::GetElementPointer(CompilerContext* context) } //todo: improve these error messages - context->root->Error("Cannot index type '" + lhs.type->base->name + "'", this->token); + context->root->Error("Cannot dereference type '" + lhs.type->base->name + "'", this->token); } else if ((p || i) && lhs.type->type == Types::Pointer) { @@ -358,12 +391,22 @@ CValue IndexExpression::GetElementPointer(CompilerContext* context) { if (this->member.text == "size") { + if (for_store) + { + context->root->Error("Cannot modify fixed array size", this->token); + } + auto loc = context->root->builder.CreateAlloca(context->root->IntType->GetLLVMType()); context->root->builder.CreateStore(context->root->builder.getInt32(lhs.type->base->size), loc); return CValue(context->root->IntType->GetPointerType(), loc); } else if (this->member.text == "ptr") { + if (for_store) + { + context->root->Error("Cannot modify fixed array ptr", this->token); + } + //just return a pointer to myself auto loc = context->root->builder.CreateGEP(lhs.val, { context->root->builder.getInt32(0), context->root->builder.getInt32(0) }); @@ -377,10 +420,8 @@ CValue IndexExpression::GetElementPointer(CompilerContext* context) { std::vector iindex = { context->root->builder.getInt32(0), context->DoCast(context->root->IntType, index->Compile(context)).val }; - //lhs.val->dump(); auto loc = context->root->builder.CreateGEP(lhs.val, iindex, "index"); - //lhs.val->getType()->dump(); - //loc->getType()->dump(); + return CValue(lhs.type->base->base->GetPointerType(), loc); } else if (lhs.type->base->type == Types::Pointer @@ -409,7 +450,14 @@ CValue IndexExpression::GetElementPointer(CompilerContext* context) return CValue(fun->return_type, context->root->builder.CreateCall(fun->f, { lhs.val, right.val }, "operator_overload")); } } - context->root->Error("Cannot index type '" + lhs.type->ToString() + "'", this->token); + if (this->token.type == TokenType::LeftBracket) + { + context->root->Error("Cannot index type '" + lhs.type->base->ToString() + "'", this->token, this->close_bracket); + } + else + { + context->root->Error("Cannot index type '" + lhs.type->base->ToString() + "'", this->token); + } } context->root->Error("Unimplemented", this->token); @@ -422,7 +470,7 @@ void IndexExpression::CompileStore(CompilerContext* context, CValue right) context->CurrentToken(&token); context->SetDebugLocation(this->token); //todo: do not allow store into .size on arrays - auto loc = this->GetElementPointer(context); + auto loc = this->GetElementPointer(context, true); context->CurrentToken(oldtok); diff --git a/Expressions.h b/Expressions.h index a67bd34..54b1a2c 100644 --- a/Expressions.h +++ b/Expressions.h @@ -19,6 +19,7 @@ namespace Jet class Expression// : public SyntaxNode { + std::string qualified_namespace_;// cache public: Token semicolon; Expression() @@ -37,6 +38,8 @@ namespace Jet this->parent = parent; } + const std::string& GetNamespaceQualifier(); + virtual CValue Compile(CompilerContext* context) = 0; virtual void CompileDeclarations(CompilerContext* context) = 0; @@ -48,6 +51,8 @@ namespace Jet virtual Type* TypeCheck(CompilerContext* context) = 0; virtual void Visit(ExpressionVisitor* visitor) = 0;//visits all subexpressions + + virtual const char* GetNamespace() { return 0; }// returns the namespace that we create, if any }; class IStorableExpression @@ -69,7 +74,7 @@ namespace Jet this->templates = templates; } - std::string GetName() + std::string GetName() const { if (this->templates) { @@ -498,7 +503,7 @@ namespace Jet CValue Compile(CompilerContext* context); - CValue GetElementPointer(CompilerContext* context); + CValue GetElementPointer(CompilerContext* context, bool for_store = false); CValue GetBaseElementPointer(CompilerContext* context); Type* GetType(CompilerContext* context, bool tc = false); @@ -968,7 +973,7 @@ namespace Jet { ii->Compile(context); } - catch (...) + catch (int i) { } diff --git a/Jet/jet.jet b/Jet/jet.jet deleted file mode 100644 index 0a31aa9..0000000 --- a/Jet/jet.jet +++ /dev/null @@ -1,84 +0,0 @@ - -fun Jet::Compilation* MakeCompilation(char* project) -{ - let Jet::Compilation q; - let c = &q;//new Jet::Compilation; - let ctx = LLVMContextCreate(); - - c->module = LLVMModuleCreateWithNameInContext("test", ctx); - let voidt = LLVMVoidTypeInContext(ctx); - - let funtype = LLVMFunctionType(voidt, 0, 0, 0); - - let char* msg = 0; - LLVMDumpType(funtype); - let fn = LLVMAddFunction(c->module, "test", funtype); - - let entry = LLVMAppendBasicBlock(fn, "entry"); - - let builder = LLVMCreateBuilderInContext(ctx); - LLVMPositionBuilderAtEnd(builder, entry); - LLVMBuildRetVoid(builder); - - LLVMPrintModuleToFile(c->module, "out.txt", &msg); - LLVMDumpModule(c->module); - - - //init stuff - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86Target(); - LLVMInitializeX86TargetMC(); - LLVMInitializeX86AsmPrinter(); - - let char* error = 0; - let triple = LLVMGetDefaultTargetTriple(); - let LLVMTargetRef target; - LLVMGetTargetFromTriple(triple, &target, &error); - - - let cpu = "haswell"; - let mach = LLVMCreateTargetMachine(target, triple, cpu, "", - 0/*level*/, 0/*reloc*/, 0/*codemodel*/); - - //local qq = LLVMGetTargetMachineData(mach); - - LLVMSetTarget(c->module, triple); - //LLVMSetDataLayout(c->module, triple);//qq); - - LLVMTargetMachineEmitToFile(mach, c->module, "test.o", 1/*codegen*/, 0); - - LLVMDisposeTargetMachine(mach); - - return c; -} - -namespace Jet -{ - struct Compiler - { - int x; - fun void Compile(char* command) - { - - } - } - - struct Compilation - { - LLVMModuleRef module; - - fun void ~Compilation() - { - LLVMDisposeModule(this->module); - } - } -} - -fun void main() -{ - let Jet::Compiler c; - - MakeCompilation("jetcore"); - - c.Compile("jetcore"); -} diff --git a/Jet/llvm-c.jet b/Jet/llvm-c.jet deleted file mode 100644 index 79155c7..0000000 --- a/Jet/llvm-c.jet +++ /dev/null @@ -1,205 +0,0 @@ - - -typedef LLVMContextRef = char*; -typedef LLVMModuleRef = char*; -typedef LLVMValueRef = char*; -typedef LLVMTypeRef = char*; -typedef LLVMBasicBlockRef = char*; -typedef LLVMBuilderRef = char*; -typedef LLVMBool = int; -typedef LLVMPassManagerRef = char*; -typedef LLVMPassRegistryRef = char*; -typedef LLVMTargetDataRef = char*; -typedef LLVMTargetMachineRef = char*; -typedef LLVMTargetRef = char*; - -extern fun void LLVMSetTarget(LLVMModuleRef m, char* triple); - -extern fun LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T); - -extern fun void LLVMSetDataLayout(LLVMModuleRef M, char* Triple); - -extern fun char* LLVMGetDefaultTargetTriple(); - -//use me! -//oops, cant do pointers to typedefs :S -extern fun LLVMBool LLVMGetTargetFromTriple (char* TripleStr, LLVMTargetRef* T, char** ErrorMessage); - -extern fun LLVMTargetMachineRef LLVMCreateTargetMachine( - LLVMTargetRef t, - char* triple, char* cpu, char* features, - int/*LLMVCodeGenOptLevel*/ level, - int/*LLVMRelocMode*/ reloc, - int/*LLVMCodeModel*/ codemodel -); -extern fun LLVMBool LLVMTargetMachineEmitToFile( - LLVMTargetMachineRef T, - LLVMModuleRef M, - char* Filename, - int/*LLVMCodeGenFileType*/ codegen, - char** ErrorMessage -); -extern fun void LLVMDisposeTargetMachine(LLVMTargetMachineRef t); - -extern fun LLVMContextRef LLVMContextCreate(); -extern fun void LLVMContextDispose(LLVMContextRef C); - -//pass stuff -extern fun LLVMPassRegistryRef LLVMGetGlobalPassRegistry(); -extern fun LLVMPassManagerRef LLVMCreatePassManager(); -extern fun LLVMPassManagerRef LLVMCreateFunctionPassManagerForModule(LLVMModuleRef m); -extern fun LLVMBool LLVMRunPassManager(LLVMPassManagerRef pm, LLVMModuleRef mod); -extern fun LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef fpm, LLVMValueRef f); -extern fun LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef fpm); -extern fun LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef fpm); - -//this stuff -extern fun LLVMBool LLVMInitializeX86TargetInfo(); -extern fun LLVMBool LLVMInitializeX86Target(); -extern fun LLVMBool LLVMInitializeX86AsmPrinter(); - -extern fun LLVMBool LLVMInitializeX86TargetMC(); -extern fun LLVMBool LLVMInitializeNativeTarget(); -extern fun LLVMBool LLVMInitializeAllTargetInfos(); -extern fun LLVMBool LLVMInitializeAllTargets(); -extern fun LLVMBool LLVMInitializeNativeASMPrinter(); -extern fun void LLVMInitializeCore(LLVMPassManagerRef r); -extern fun void LLVMInitializeCodeGen(LLVMPassManagerRef r); -extern fun void LLVMInitializeTarget(LLVMPassManagerRef r); - -extern fun LLVMTargetDataRef LLVMCreateTargetData(char* stringrep); -extern fun void LLVMAddTargetData(LLVMTargetDataRef td, LLVMPassManagerRef ref); -extern fun void LLVMDisposeTargetData(LLVMTargetDataRef td); - -extern fun LLVMModuleRef LLVMModuleCreateWithName(char* ModuleID); -extern fun LLVMModuleRef LLVMModuleCreateWithNameInContext(char* ModuleID, LLVMContextRef C); - -extern fun void LLVMDisposeModule(LLVMModuleRef M); -extern fun void LLVMSetDataLayout(LLVMModuleRef M, char* Triple); -extern fun void LLVMSetTarget(LLVMModuleRef M, char* Triple); - -extern fun void LLVMDumpModule(LLVMModuleRef M); - -extern fun LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, char *Filename, - char **ErrorMessage); - -extern fun LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, char *Name); - -extern fun LLVMValueRef LLVMAddFunction(LLVMModuleRef M, char *Name, - LLVMTypeRef FunctionTy); -extern fun LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType, - LLVMTypeRef *ParamTypes, int/*unsigned*/ ParamCount, - LLVMBool IsVarArg); - -extern fun LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, /*unsigned*/int ElementCount, - LLVMBool Packed); - - -extern fun LLVMTypeRef LLVMPointerType(LLVMTypeRef ElementType, /*unsigned*/int AddressSpace); - -extern fun void LLVMDumpType(LLVMTypeRef Val); - -extern fun void LLVMPositionBuilderAtEnd(LLVMBuilderRef builder, LLVMBasicBlockRef block); - -extern fun LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef fn, char* name); -//types -extern fun LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C); -extern fun LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C); -extern fun LLVMTypeRef LLVMInt8TypeInContext(LLVMContextRef C); -extern fun LLVMTypeRef LLVMInt16TypeInContext(LLVMContextRef C); -extern fun LLVMTypeRef LLVMInt32TypeInContext(LLVMContextRef C); -extern fun LLVMTypeRef LLVMInt64TypeInContext(LLVMContextRef C); -//extern fun LLVMTypeRef LLVMIntTypeInContext(LLVMContextRef C, unsigned NumBits); -extern fun LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C); -extern fun LLVMTypeRef LLVMDoubleTypeInContext(LLVMContextRef C); - - -extern fun LLVMTypeRef LLVMTypeOf(LLVMValueRef Val); - -extern fun void LLVMDumpValue(LLVMValueRef Val); - - -extern fun LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N); -extern fun LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, long/*unsigned long long*/ N, - LLVMBool SignExtend); -extern fun LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, char *Str, - /*unsigned*/int Length, LLVMBool DontNullTerminate); - -extern fun LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, char *Name); - - -extern fun LLVMBasicBlockRef LLVMInsertBasicBlockInContext(LLVMContextRef C, - LLVMBasicBlockRef BB, - char *Name); - - - - -extern fun LLVMBuilderRef LLVMCreateBuilderInContext(LLVMContextRef C); -extern fun void LLVMDisposeBuilder(LLVMBuilderRef Builder); - - -extern fun void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L); -extern fun LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder); - - -//terminators -extern fun LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef x); -extern fun LLVMValueRef LLVMBuildRet(LLVMBuilderRef x, LLVMValueRef V); -extern fun LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef x, LLVMValueRef V, - LLVMBasicBlockRef Else, /*unsigned*/int NumCases); -extern fun LLVMValueRef LLVMBuildBr(LLVMBuilderRef x, LLVMBasicBlockRef Dest); -extern fun LLVMValueRef LLVMBuildCondBr(LLVMBuilderRef x , LLVMValueRef If, - LLVMBasicBlockRef Then, LLVMBasicBlockRef Else); - -extern fun void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, - LLVMBasicBlockRef Dest); - -extern fun LLVMValueRef LLVMBuildAdd(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildFAdd(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildSub(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildFSub(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildMul(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); - -extern fun LLVMValueRef LLVMBuildFMul(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildFDiv(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); - -extern fun LLVMValueRef LLVMBuildAnd(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildOr(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); -extern fun LLVMValueRef LLVMBuildXor(LLVMBuilderRef x, LLVMValueRef LHS, LLVMValueRef RHS, - char *Name); - -extern fun LLVMValueRef LLVMBuildNeg(LLVMBuilderRef x, LLVMValueRef V, char *Name); -extern fun LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef x, LLVMValueRef V, char *Name); -extern fun LLVMValueRef LLVMBuildNot(LLVMBuilderRef x, LLVMValueRef V, char *Name); - - - -//memory -extern fun LLVMValueRef LLVMBuildLoad(LLVMBuilderRef x, LLVMValueRef PointerVal, - char *Name); -extern fun LLVMValueRef LLVMBuildStore(LLVMBuilderRef x, LLVMValueRef Val, LLVMValueRef Ptr); -extern fun LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer, - LLVMValueRef *Indices, /*unsigned*/int NumIndices, - char *Name); - -//casts -extern fun LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef x, LLVMValueRef Val, - LLVMTypeRef DestTy, char *Name); - - -//others -extern fun LLVMValueRef LLVMBuildCall(LLVMBuilderRef x, LLVMValueRef Fn, - LLVMValueRef *Args, /*unsigned*/int NumArgs, - char *Name); - - \ No newline at end of file diff --git a/Jet/project.jp b/Jet/project.jp deleted file mode 100644 index 9b1ad02..0000000 --- a/Jet/project.jp +++ /dev/null @@ -1,45 +0,0 @@ - -requires: ../jetc -libs: "C:\Users\Matthew\Desktop\llvm-3.7\Debug\lib\LLVMCore.lib" -"C:\Users\Matthew\Desktop\llvm-3.7\Debug\lib\LLVMObject.lib" -"C:\Users\Matthew\Desktop\llvm-3.7\Debug\lib\LLVMSupport.lib" -"C:\Users\Matthew\Desktop\llvm-3.7\Debug\lib\LLVMTarget.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMAnalysis.lib" -"C:/Users/Matthew/Desktop/llvm-3.7/Debug/lib/LLVMExecutionEngine.lib" - -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMInstrumentation.lib" - -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMMC.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMMCDisassembler.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMMCParser.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMMCJIT.lib" - -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMCodeGen.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMBitReader.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMScalarOpts.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMTransformUtils.lib" - -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMAsmPrinter.lib" - -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMSelectionDAG.lib" - -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMipa.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMipo.lib" - - -"C:/Users/Matthew/Desktop/llvm-3.7/Debug/lib/LLVMX86CodeGen.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMX86AsmPrinter.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMX86Desc.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMX86Info.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMX86Utils.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMX86AsmParser.lib" -"C:/Users/Matthew/Desktop/llvm-3.7\Debug\lib\LLVMX86Utils.lib" - -"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\uuid.lib" -"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\shell32.lib" -"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\psapi.lib" -"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\advapi32.lib" - "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcprtd.lib" - "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrtd.lib" - "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\OLDNAMES.lib" - "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" \ No newline at end of file diff --git a/Jet/types.jet b/Jet/types.jet deleted file mode 100644 index 8cdfa7b..0000000 --- a/Jet/types.jet +++ /dev/null @@ -1,52 +0,0 @@ - -namespace Jet -{ - struct Namespace - { - char* name; - } - - struct Type - { - int type; - bool loaded; - - - //for arrays - int size; - - Namespace* ns; - - char* name; - - //fun void Type() - //{ - - //} - - //fun void Type(char* name) - //{ - - //} - - fun char* ToString() - { - return 0; - } - - fun LLVMTypeRef GetLLVMType() - { - return 0; - } - - fun Type* GetPointerType() - { - return 0; - } - - fun Type* GetBaseType() - { - return 0; - } - } -} diff --git a/Lexer.cpp b/Lexer.cpp index e38280d..c0b0fb7 100644 --- a/Lexer.cpp +++ b/Lexer.cpp @@ -65,6 +65,8 @@ class LexerStatic operators["&="] = TokenType::AndAssign; operators["|="] = TokenType::OrAssign; operators["^="] = TokenType::XorAssign; + operators["<<="] = TokenType::ShlAssign; + operators[">>="] = TokenType::ShrAssign; //boolean logic operators["!="] = TokenType::NotEqual; @@ -105,6 +107,7 @@ class LexerStatic keywords["for"] = TokenType::For; keywords["let"] = TokenType::Let; + keywords["const"] = TokenType::Const; keywords["break"] = TokenType::Break; keywords["continue"] = TokenType::Continue; @@ -124,6 +127,7 @@ class LexerStatic keywords["union"] = TokenType::Union; keywords["extern"] = TokenType::Extern; + keywords["extern_c"] = TokenType::Extern; keywords["struct"] = TokenType::Struct; keywords["class"] = TokenType::Class; keywords["namespace"] = TokenType::Namespace; @@ -144,9 +148,7 @@ class LexerStatic operators["#endif"] = TokenType::EndIfMacro; operators["//!@!"] = TokenType::LocationMacro; - //keywords["const"] = TokenType::Const; - - //keywords["operator"] = TokenType::Operator; + for (auto ii = operators.begin(); ii != operators.end(); ii++) { @@ -169,6 +171,7 @@ class LexerStatic TokenToString[ii.second] = ii.first; TokenToString[TokenType::Name] = "name"; + TokenToString[TokenType::Number] = "number"; } }; @@ -496,8 +499,9 @@ Token Lexer::Next() } else if (IsNumber(c))//number { - //finish adding different literal types - if (c != '0') + char next_char = src->PeekChar(); + // Check if it is a standard integer or floating point number + if (c != '0' || next_char == '.') { std::string num; num += c; @@ -524,7 +528,7 @@ Token Lexer::Next() //ok, its possibly some kind of non base ten literal std::string num; num += c; - char c = src->PeekChar(); + char c = next_char; num += c; switch (c) { diff --git a/OptionParser.h b/OptionParser.h index bd00926..f7fe881 100644 --- a/OptionParser.h +++ b/OptionParser.h @@ -75,7 +75,7 @@ class OptionParser { char* command = new char[aargs.size()+1]; strcpy(command, aargs.c_str()); - char* args[400] = {}; + const char* args[400] = {}; int numargs = 0; int i = 0; bool inquotes = false; @@ -111,7 +111,7 @@ class OptionParser delete[] command; } - void Parse(int argc, char ** args) + void Parse(int argc, const char ** args) { for (int i = 1; i < argc; i++) { @@ -182,4 +182,4 @@ class OptionParser } } } -}; \ No newline at end of file +}; diff --git a/Parselets.cpp b/Parselets.cpp index 8ebeb9d..d13b1cb 100644 --- a/Parselets.cpp +++ b/Parselets.cpp @@ -1054,7 +1054,7 @@ Expression* ReturnParselet::parse(Parser* parser, Token token) Expression* LocalParselet::parse(Parser* parser, Token token) { - UniquePtr>*> names = new std::vector < std::pair > ; + UniquePtr*> names = new std::vector < LetExpression::TypeNamePair > ; do { diff --git a/Parser.cpp b/Parser.cpp index f73aa8c..af8f04c 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -37,7 +37,8 @@ Parser::Parser(Lexer* l, DiagnosticBuilder* diag) this->Register(TokenType::AndAssign, new OperatorAssignParselet()); this->Register(TokenType::OrAssign, new OperatorAssignParselet()); this->Register(TokenType::XorAssign, new OperatorAssignParselet()); - + this->Register(TokenType::ShlAssign, new OperatorAssignParselet()); + this->Register(TokenType::ShrAssign, new OperatorAssignParselet()); //prefix stuff this->Register(TokenType::Increment, new PrefixOperatorParselet(Precedence::PREFIX)); @@ -106,6 +107,7 @@ Parser::Parser(Lexer* l, DiagnosticBuilder* diag) this->Register(TokenType::Default, new DefaultParselet()); this->Register(TokenType::Let, new LocalParselet()); + this->Register(TokenType::Const, new LocalParselet()); this->Register(TokenType::Extern, new ExternParselet()); this->Register(TokenType::Struct, new StructParselet()); @@ -124,7 +126,6 @@ Parser::Parser(Lexer* l, DiagnosticBuilder* diag) this->Register(TokenType::Typedef, new TypedefParselet()); - //this->Register(TokenType::Const, new ConstParselet()); //this->Register(TokenType::Null, new NullParselet()); this->Register(TokenType::Yield, new YieldParselet()); diff --git a/README.md b/README.md index b526330..97251ae 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Lets start by making a source file named "main.jet" and adding it to the list of Inside this file put: ```cpp -extern fun int puts(char* text); +extern_c fun int puts(char* text); fun int main() { diff --git a/Token.h b/Token.h index 6905b1d..33f77c8 100644 --- a/Token.h +++ b/Token.h @@ -38,6 +38,8 @@ namespace Jet AndAssign, OrAssign, XorAssign, + ShrAssign, + ShlAssign, NotEqual, Equals, diff --git a/Types/Function.cpp b/Types/Function.cpp index 3e3f23c..80f27b8 100644 --- a/Types/Function.cpp +++ b/Types/Function.cpp @@ -8,6 +8,35 @@ using namespace Jet; +static unsigned int uuid = 5; +std::string mangle(const std::string& name, bool is_lambda, const std::vector>& arguments, bool is_c_function) +{ + // handle main + if (name == "main") + { + return name; + } + if (name == "_init") + { + return name; + } + if (is_lambda) + { + return name + std::to_string(uuid++); + } + if (is_c_function) + { + return name; + } + // todo actually mangle + return name + "_" + std::to_string(arguments.size()); +} + +Function::~Function() +{ + delete this->context; +} + void Function::Load(Compilation* compiler) { if (this->loaded) @@ -52,7 +81,10 @@ void Function::Load(Compilation* compiler) ft = llvm::FunctionType::get(this->return_type->GetLLVMType(), args, false); } - this->f = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, name, compiler->module); + // todo need to know if this is a C function, if it is we shouldnt mangle + const auto mangled_name = mangle(name, this->is_lambda, arguments, is_c_function); + + this->f = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, mangled_name, compiler->module); switch (this->calling_convention) { case CallingConvention::StdCall: @@ -66,15 +98,21 @@ void Function::Load(Compilation* compiler) break; } - llvm::DIFile* unit = compiler->debug_info.file; + // dont add debug info for externs (todo also handle jet externs) + if (!is_c_function && context) + { + llvm::DIFile* unit = compiler->debug_info.file; + + auto functiontype = compiler->debug->createSubroutineType(compiler->debug->getOrCreateTypeArray(ftypes)); + int line = this->expression ? this->expression->token.line : 0; + llvm::DISubprogram* sp = compiler->debug->createFunction(unit, this->name, mangled_name, unit, line, functiontype, false, true, line, llvm::DINode::DIFlags::FlagPublic, false, nullptr);// , f); - auto functiontype = compiler->debug->createSubroutineType(compiler->debug->getOrCreateTypeArray(ftypes)); - int line = this->expression ? this->expression->token.line : 0; - llvm::DISubprogram* sp = compiler->debug->createFunction(unit, this->name, this->name, unit, line, functiontype, false, true, line, llvm::DINode::DIFlags::FlagPublic, false, nullptr);// , f); + // this catches duplicates or incorrect functions + assert(sp->describes(f)); + this->scope = sp; - assert(sp->describes(f)); - this->scope = sp; - compiler->builder.SetCurrentDebugLocation(llvm::DebugLoc::get(5, 1, 0)); + f->setSubprogram(sp); + } //alloc args auto AI = f->arg_begin(); @@ -242,7 +280,7 @@ CValue Function::Call(CompilerContext* context, const std::vector& argsv //was ii.val, but this makes more sense auto sptr = context->root->builder.CreatePointerCast(ii.pointer, context->root->CharPointerType->GetLLVMType()); auto dptr = context->root->builder.CreatePointerCast(alloc, context->root->CharPointerType->GetLLVMType()); - context->root->builder.CreateMemCpy(dptr, sptr, type->GetSize(), 1); + context->root->builder.CreateMemCpy(dptr, 0, sptr, 0, type->GetSize());// todo properly handle alignment } } else diff --git a/Types/Function.h b/Types/Function.h index 9b544c3..a449d57 100644 --- a/Types/Function.h +++ b/Types/Function.h @@ -55,6 +55,7 @@ namespace Jet FunctionType* type; CallingConvention calling_convention; + // the prefix for the mangled function name std::string name; std::vector> arguments; @@ -81,6 +82,9 @@ namespace Jet llvm::StructType* storage_type;//for lambdas } lambda; + // Mangling related settings + bool is_c_function = false; + //virtual stuff bool is_virtual = false; int virtual_offset = -1; @@ -97,12 +101,13 @@ namespace Jet bool loaded; - Function(const std::string& name, bool is_lambda) + Function(const std::string& name, bool is_lambda, bool is_c_function = false) { this->calling_convention = CallingConvention::Default; - this->do_export = true; + this->do_export = !is_lambda; this->name = name; this->generator.var_num = 0; + this->is_c_function = is_c_function; context = 0; f = 0; this->is_lambda = is_lambda; @@ -112,10 +117,7 @@ namespace Jet this->is_generator = false; } - ~Function() - { - delete this->context; - } + ~Function(); CValue Call(CompilerContext* context, const std::vector& argsv, bool devirtualize); @@ -141,4 +143,4 @@ namespace Jet Function* Instantiate(Compilation* compiler, const std::vector& types); }; } -#endif \ No newline at end of file +#endif diff --git a/Types/Types.cpp b/Types/Types.cpp index 257d5c1..962129d 100644 --- a/Types/Types.cpp +++ b/Types/Types.cpp @@ -122,7 +122,7 @@ llvm::DIType* Type::GetDebugType(Compilation* compiler) std::vector ftypes; int offset = 0; auto list = { compiler->IntType, this->base->GetPointerType() }; - char* names[] = { "size", "ptr" }; + const char* names[] = { "size", "ptr" }; int i = 0; for (auto type : list) { @@ -1131,6 +1131,27 @@ Namespace::~Namespace() } } +const std::string& Namespace::GetQualifiedName() +{ + if (qualified_name_.length()) + { + return qualified_name_; + } + + if (this->parent) + { + qualified_name_ = this->parent->GetQualifiedName(); + if (qualified_name_.length()) + qualified_name_ += "::"; + qualified_name_ += name; + } + else + { + qualified_name_ = name; + } + return qualified_name_; +} + //todo, condense the data later using numeric identifiers and a list rather than whole name on each also could sort by file void add_location(Token token, std::string& data, Compilation* compilation) { @@ -1431,4 +1452,4 @@ llvm::Constant* Type::GetDefaultValue(Compilation* compilation) throw 7; } return initializer; -} \ No newline at end of file +} diff --git a/Types/Types.h b/Types/Types.h index ebb9cae..2d34162 100644 --- a/Types/Types.h +++ b/Types/Types.h @@ -39,7 +39,7 @@ namespace Jet llvm::Value* GetReference(); }; - enum class Types + enum class Types: char { Void,//valid really only as a return type Double,//64 bit float @@ -162,7 +162,7 @@ namespace Jet }; - enum class SymbolType + enum class SymbolType: char { Invalid, Namespace, @@ -222,6 +222,11 @@ namespace Jet } void OutputMetadata(std::string& data, Compilation* comp); + + const std::string& GetQualifiedName(); + + private: + std::string qualified_name_; }; struct Function; @@ -282,4 +287,4 @@ namespace Jet llvm::Type* type; }; } -#endif \ No newline at end of file +#endif diff --git a/jetc.cpp b/jetc.cpp index 0346351..dcbab25 100644 --- a/jetc.cpp +++ b/jetc.cpp @@ -19,7 +19,12 @@ #include #include #include + +#ifdef _WIN32 #include +#else +#include +#endif using namespace Jet; @@ -482,7 +487,7 @@ void MakeDocs(Compilation* compilation) of << out; } -void DoCommand(int argc, char* argv[]) +void DoCommand(int argc, const char* argv[]) { std::string cmd = argc > 1 ? argv[1] : ""; if (cmd == "projects") @@ -515,7 +520,7 @@ void DoCommand(int argc, char* argv[]) if (parser.commands.size()) config = parser.commands.front(); - std::vector programs = { "OperatorOverloads", "SmartPointerTest", "Globals", "NewFree", "Namespaces", "Inheritance", "ExtensionMethods", "Generators", "IfStatements", "Unions", "ForLoop", "OperatorPrecedence", "DefaultConstructors", "Enums" }; + std::vector programs = { "OperatorOverloads", "SmartPointerTest", "Globals", "NewFree", "Namespaces", "Inheritance", "ExtensionMethods", "Generators", "IfStatements", "Unions", "ForLoop", "OperatorPrecedence", "DefaultConstructors", "Enums" }; for (auto ii : programs) @@ -604,7 +609,7 @@ void DoCommand(int argc, char* argv[]) { std::string name = argv[2]; - mkdir(name.c_str()); + mkdir(name.c_str(), 0x755); //insert a project file and a main code file @@ -681,13 +686,27 @@ std::string exec_path(const char *argv0) } return buf; } +#else + +#include +std::string exec_path(const char* argv0) +{ + char dest[PATH_MAX]; + memset(dest,0,sizeof(dest)); // readlink does not null terminate! + if (readlink("/proc/self/exe", dest, PATH_MAX) == -1) { + perror("readlink"); + } else { + //printf("%s\n", dest); + } + return dest; +} #endif #include #include std::string executable_path; -int main(int argc, char* argv[]) +int main(int argc, const char* argv[]) { #ifdef _WIN32 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); @@ -726,7 +745,7 @@ int main(int argc, char* argv[]) //split the string { - char* args[400] = {}; + const char* args[400] = {}; int numargs = 0; int i = 0; bool inquotes = false; diff --git a/tests/Arrays/test.jet b/tests/Arrays/test.jet index 4aac344..08acf3e 100644 --- a/tests/Arrays/test.jet +++ b/tests/Arrays/test.jet @@ -1,18 +1,20 @@ -extern fun int printf(char* h, int h); -extern fun char* malloc(int x); +extern_c fun int printf(char* h, int h); +extern_c fun char* malloc(int x); -extern fun void free(char* x); +extern_c fun void free(char* x); -extern fun int puts(char* str); +extern_c fun int puts(char* str); -extern fun char getchar(); +extern_c fun char getchar(); + +fun void _chkstk() {} /* array internal format looks like so: struct Array { int size; - T* values; + T* ptr; } internally implemented as passing this struct arround @@ -23,63 +25,115 @@ trait Any { } -struct __Array +/*struct __Array { int size; T* values; -} +}*/ -fun void test(int[] array) +struct ArrayUser { - for (let i = 0; i < array.size; i++) - puts("one\n"); - //array[i] = 5; + int[6] array; + int test; } -//ok virtual texturing -//indirection texture that is per 32x32 section of verts that gives x and y offset into indirection texture as well as a scale -//this is used to get texture from virtual page table which is 4k by 2k -//can later compress this to make it faster +let int[10] global; -fun int main() +fun void test_function(int[] array, int desired_size) { - let int[5] y; - for (let i = 0; i < y.size; i++) + for (let i = 0; i < array.size; i++) { - //puts("one\n"); - y[i] = 5; + printf("Value %i\n", array[i]); } + // check that the size is good + if (array.size != desired_size) + { + puts("ERROR: The array size does not match in the function!\n"); + } +} + +fun void test_static_local_array() +{ + let desired_size = 50; + let int[50] y; - test(y); + // Tests illegally mutating the static array. The following lines should error: + //y.size = 4; + //y.ptr = 0; - let x = new int[25]; - for (let i = 0; i < x.size; i++) + // The following lines should work + y.ptr[0] = 42; + y[0] = 42; + let yptr = y.ptr; + let ysize = y.size; + + // Make sure we can assign to each value + for (let i = 0; i < y.size; i++) { - x[i] = 5; - puts("two\n"); + // Use each method just in case + y[i] = i; + y.ptr[i] = i; + + if (y[i] != i || y.ptr[i] != i) + { + puts("ERROR: Value read does not match assigned!"); + } } - test(x); - //x.ptr = 0; + // Make sure the size is correct + if (y.size != desired_size) + { + puts("ERROR: The array size is incorrect!\n"); + } - //free x; - //free y; + // Make sure we can use it as an argument + test_function(y, y.size); - x[5] = 0; - x[24] = 5; - y[4] = 5; + // Try copying then check the size and values + let y_copy = y; - for (let i = 0; i < x.size; i++) + if (y_copy.size != desired_size) { - x[i] = 5; - puts("two\n"); + puts("ERROR: The copied array size is incorrect!\n"); } - free x; +} + +fun void assign_test() +{ + let int[5000] y; + + /*for (let i = 0; i < y.size; i++) + { + y[i] = i; + }*/ + + let y_copy = y; + + /*if (y_copy.size != y.size) + { + puts("ERROR: The copied array size is incorrect!\n"); + }*/ + puts("Finished copy"); + + /*for (let i = 0; i < y_copy.size; i++) + { + // Use each method just in case + if (y_copy[i] != y[i]) + { + puts("ERROR: Value in the copy doesnt match original!"); + } + puts("1"); + }*/ +} + +fun int main() +{ + test_static_local_array(); - //free y; + assign_test(); - //getchar(); + getchar(); return 0; } \ No newline at end of file diff --git a/tests/Const/project.jp b/tests/Const/project.jp new file mode 100644 index 0000000..99d157c --- /dev/null +++ b/tests/Const/project.jp @@ -0,0 +1,7 @@ +bin: Const +requires: +files: test.jet +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/Const/test.jet b/tests/Const/test.jet new file mode 100644 index 0000000..9e67bd9 --- /dev/null +++ b/tests/Const/test.jet @@ -0,0 +1,33 @@ + +extern_c fun int printf(char* h, int h); +extern_c fun char* malloc(int x); + +extern_c fun int puts(char* str); +extern_c fun char getchar(); + +let int global_mut = 7; +//const int global_const = 7;// this errors (for now) + +fun int main() +{ + // A basic checkout of const + let x = 5; + const y = 5; + + // Allowed! + x = y; + x *= 5; + x *= y; + x += 7; + x = y + 7; + + // Not allowed! + /*y = x; + y += 5; + y *= 2; + y -= 7;*/ + + getchar(); + + return 0; +} diff --git a/tests/Enums/project.jp b/tests/Enums/project.jp index f4823ed..7594789 100644 --- a/tests/Enums/project.jp +++ b/tests/Enums/project.jp @@ -1,4 +1,7 @@ - +bin: Enums requires: files: test.jet -libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" \ No newline at end of file +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/Enums/test.jet b/tests/Enums/test.jet index 67b5794..7e77ec0 100644 --- a/tests/Enums/test.jet +++ b/tests/Enums/test.jet @@ -3,6 +3,7 @@ extern fun int printf(char* h, int h); extern fun char* malloc(int x); extern fun int puts(char* str); +extern fun char getchar(); enum Test { @@ -12,5 +13,9 @@ enum Test fun int main() { + printf("%i\n", EnumA); + printf("%i\n", EnumB); + + getchar(); return EnumB; } \ No newline at end of file diff --git a/tests/ExtensionMethods/project.jp b/tests/ExtensionMethods/project.jp index f4823ed..8b947e5 100644 --- a/tests/ExtensionMethods/project.jp +++ b/tests/ExtensionMethods/project.jp @@ -1,4 +1,7 @@ - +bin: ExtensionMethods requires: files: test.jet -libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" \ No newline at end of file +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/ExtensionMethods/test.jet b/tests/ExtensionMethods/test.jet index 115ac93..79e2806 100644 --- a/tests/ExtensionMethods/test.jet +++ b/tests/ExtensionMethods/test.jet @@ -3,18 +3,37 @@ extern fun int printf(char* h, int h); extern fun char* malloc(int x); extern fun int puts(char* str); +extern fun char getchar(); + +fun void _chkstk() +{ + +} struct B { int b_val; - + int q; + char[5000] aarr; + D d; fun void T() { } } +struct D +{ + char[8000] data; +} + +fun D test() +{ + let D p; + return p; +} + fun void B::Extension() { printf("pass", 0); @@ -22,9 +41,24 @@ fun void B::Extension() fun int main() { - let x = B(); + let B x; + let B y; + let B z; + let B a; + //let B y; + //let B y; + //x = B(); + //x = y; + //x.d = y.d; + //let D q = test(); + + //x.aarr = y.aarr; + x.Extension(); x.Extension(); + getchar(); + getchar(); + return 0; } \ No newline at end of file diff --git a/tests/Generators/test.jet b/tests/Generators/test.jet index ed52d1c..c509d76 100644 --- a/tests/Generators/test.jet +++ b/tests/Generators/test.jet @@ -4,12 +4,24 @@ extern fun char* malloc(int x); extern fun int puts(char* str); +extern fun char getchar(); + +struct function +{ + T ptr; + char data[64]; +} + +trait Any +{ +} + trait IEnumerator { fun TT Current(); fun void Reset(); - fun int MoveNext(); + fun bool MoveNext(); } trait IEnumerable @@ -20,12 +32,21 @@ trait IEnumerable fun void IEnumerable::Print() { let enumer = this->GetEnumerator(); - while (enumer.MoveNext() == 1) + while (enumer.MoveNext())// == 1) { puts("Got one!"); } } +fun void IEnumerator::Test() +{ + while (this->MoveNext())// == 1) + { + puts("testing"); + printf("Number %i\n", this->Current()); + } +} + generator int test(char qp) { let short y = 7; @@ -52,20 +73,83 @@ generator int power(int number, int exponent) } } +/*struct WhereIterable +{ + Base* iterable; + function fn; + + fun WhereIterator> GetEnumerator() + { + let WhereIterator> x; + x.iter = this->iterable->GetEnumerator(); + x.fn = this->fn; + return x; + } +} + +struct WhereIterator +{ + Base iter; + function fn; + + fun T Current() + { + return this->iter.Current(); + } + + fun void Reset() + { + this->iter.Reset(); + } + + fun int MoveNext() + { + while (this->iter.MoveNext()) + { + let fn = this->fn; + if (fn(this->iter.Current())) + return 1; + } + return 0; + } +}*/ + +fun WhereIterable IEnumerable::Where(function fn) +{ + let WhereIterable x; + x.iterable = this; + x.fn = fn; + return x; +} + fun int main() -{ +{ let x = power(2, 20); let p = 0; while (x.MoveNext()) { p = x.Current(); - //printf("%i\n", x.Current()); + printf("%i\n", x.Current()); } if (p != 1048576) puts("fail"); else puts("pass"); - + x.Reset(); + while (x.MoveNext()) + { + p = x.Current(); + printf("Number %i\n", x.Current()); + } + x.Reset(); + x.Test(); + x.Test(); + + let fn = [](int x) -> bool { return x > 5; }; + if (fn(5)) + puts("fail"); + + //let where = x.Where(fn); let t = test(5); while (t.MoveNext()) { @@ -74,6 +158,8 @@ fun int main() } if (p != 3) puts("fail"); + + getchar(); return 0; } \ No newline at end of file diff --git a/tests/IfStatements/project.jp b/tests/IfStatements/project.jp index f4823ed..337859d 100644 --- a/tests/IfStatements/project.jp +++ b/tests/IfStatements/project.jp @@ -1,4 +1,7 @@ - +bin: IfStatements requires: files: test.jet -libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" \ No newline at end of file +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/IfStatements/test.jet b/tests/IfStatements/test.jet index 6ca3c4c..ae41844 100644 --- a/tests/IfStatements/test.jet +++ b/tests/IfStatements/test.jet @@ -4,6 +4,8 @@ extern fun char* malloc(int x); extern fun int puts(char* str); +extern fun char getchar(); + fun int main() { let x = 1; @@ -21,5 +23,7 @@ fun int main() puts("fail"); } + getchar(); + return 0; } \ No newline at end of file diff --git a/tests/Lambdas/project.jp b/tests/Lambdas/project.jp index 68728d6..6d8720b 100644 --- a/tests/Lambdas/project.jp +++ b/tests/Lambdas/project.jp @@ -1,4 +1,7 @@ - +bin: Lambdas requires: JetCore files: test.jet -libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" \ No newline at end of file +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/LargeCopy/project.jp b/tests/LargeCopy/project.jp new file mode 100644 index 0000000..6a91fb3 --- /dev/null +++ b/tests/LargeCopy/project.jp @@ -0,0 +1,10 @@ +bin: LargeCopy +requires: +files: test.jet +libs: "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\ucrt\x86\ucrt.lib" +"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\ucrt\x86\libucrt.lib" + "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\x86\kernel32.lib" + "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\lib\x86\msvcrt.lib" + +[debug] +config: "-f --linker ld" \ No newline at end of file diff --git a/tests/LargeCopy/test.jet b/tests/LargeCopy/test.jet new file mode 100644 index 0000000..52fd21d --- /dev/null +++ b/tests/LargeCopy/test.jet @@ -0,0 +1,27 @@ + +extern fun int printf(char* h, int h); +extern fun char* malloc(int x); + +extern fun void free(char* x); + +extern fun int puts(char* str); + +extern fun char getchar(); + +//fun void _chkstk() {} + +fun char* memcpy(char* x, char* y, int size) +{ + return 0; +} + +fun int main() +{ + let int[5000] y; + + let y_copy = y; + + getchar(); + + return 0; +} \ No newline at end of file diff --git a/tests/Literals/project.jp b/tests/Literals/project.jp new file mode 100644 index 0000000..91a0fb9 --- /dev/null +++ b/tests/Literals/project.jp @@ -0,0 +1,7 @@ +bin: Literals +requires: +files: test.jet +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/Literals/test.jet b/tests/Literals/test.jet new file mode 100644 index 0000000..b32d426 --- /dev/null +++ b/tests/Literals/test.jet @@ -0,0 +1,89 @@ + +extern fun int printf(char* h, int h); +extern fun char* malloc(int x); + +extern fun int puts(char* str); +extern fun char getchar(); + +// okay, lets come up with a test infrastructure +// try and implement it mostly in this + +struct Test +{ + char* name; + void() function; +} + +let vector tests; + +fun void add_test(char* name, void() function) +{ + let Test t; + t.name = name; + t.function = function; + tests.push_back(t); +} + +fun void EXPECT(bool condition, char* message) +{ + if (condition) + { + return;// we're good! + } + // we failed.... add this to the test + //puts(" + +} + +fun void run_tests() +{ + for (let i = 0; i < tests.size(); i++) + { + + } +} + +fun int main() +{ + // lets test some numeric literals! + let binary = 0b11111111; + let hex = 0xFF; + let numeric = 255; + + if (hex != 255) + { + puts("Hex didnt work!"); + } + if (binary != 255) + { + puts("Hex didnt work!"); + } + if (numeric != hex) + { + puts("Numeric and hex were not equal!"); + } + + // Test floating point literals + let f1 = 10.7f; + let f2 = 0.7f; //this one has broken the lexer before + let d = 0.7; + + let x = 7; + x += 2; + + let char y = 7; + + x += y; + + //y = x; + + y = 23.0f; + + y = 2*y; + y = y*2; + y = (2+2); + //y = x*2; + getchar(); + + return 0; +} \ No newline at end of file diff --git a/tests/Namespaces/project.jp b/tests/Namespaces/project.jp index f4823ed..777863f 100644 --- a/tests/Namespaces/project.jp +++ b/tests/Namespaces/project.jp @@ -1,4 +1,7 @@ - +bin: Namespaces requires: files: test.jet -libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" \ No newline at end of file +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/Namespaces/test.jet b/tests/Namespaces/test.jet index c03daf6..b6b5b3e 100644 --- a/tests/Namespaces/test.jet +++ b/tests/Namespaces/test.jet @@ -4,6 +4,8 @@ extern fun char* malloc(int x); extern fun int puts(char* str); +extern fun char getchar(); + namespace Tests::Hello { struct A @@ -11,21 +13,44 @@ namespace Tests::Hello int a_val; } - struct B: A + struct B//: A { int b_val; } + + fun void test() + { + puts("I am in the A namespace!"); + } } namespace Tests { - struct C: Hello::B + struct C { int c_val; Apple apple; } } +namespace nsB +{ + struct A + { + int a_val2; + } + + struct B + { + int b_val2; + } + + fun void test() + { + puts("I am in the B namespace!"); + } +} + struct Apple { int seeds; @@ -35,11 +60,18 @@ struct Apple fun int main() { - let Tests::C x; + let Tests::C z; + + let Tests::Hello::A x; let Tests::Hello::B y; - let Tests::Hello::A z; x.a_val = 1; - x.b_val = 2; - x.c_val = 3; + y.b_val = 1; + + let nsB::A a; + let nsB::B b; + a.a_val2 = 1; + b.b_val2 = 1; + + getchar(); return 0; } \ No newline at end of file diff --git a/tests/NewFree/test.jet b/tests/NewFree/test.jet index 2b4a3d7..ca13cfd 100644 --- a/tests/NewFree/test.jet +++ b/tests/NewFree/test.jet @@ -10,14 +10,14 @@ struct t { fun void t() { - count++; + //count++; //puts("created\n"); } - fun void ~t() + /*fun void ~t() { - count--; + //count--; //puts("killed\n"); - } + }*/ } fun int main() diff --git a/tests/OperatorOverloads/test.jet b/tests/OperatorOverloads/test.jet index c31b5cd..81291b6 100644 --- a/tests/OperatorOverloads/test.jet +++ b/tests/OperatorOverloads/test.jet @@ -47,7 +47,7 @@ struct B //int* data; fun int* operator[](int index) { - return &this->data[index]; + return &(this->data[index]); } } @@ -78,7 +78,7 @@ fun int main() else puts("pass\n"); - printf("%i", q[5]); - //getchar(); + //printf("%i", q[5]); + getchar(); return 0; } \ No newline at end of file diff --git a/tests/Overloads/project.jp b/tests/Overloads/project.jp new file mode 100644 index 0000000..ff173ce --- /dev/null +++ b/tests/Overloads/project.jp @@ -0,0 +1,7 @@ +bin: Overloads +requires: +files: test.jet +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +config: "--linker ld" \ No newline at end of file diff --git a/tests/Overloads/test.jet b/tests/Overloads/test.jet new file mode 100644 index 0000000..b398e3b --- /dev/null +++ b/tests/Overloads/test.jet @@ -0,0 +1,37 @@ + +extern fun int printf(char* h, int h); +extern fun char* malloc(int x); + +extern fun int puts(char* str); + +extern fun char getchar(); + +fun void test(int a, int b) +{ + puts("2 argument\n"); +} + +fun void test() +{ + puts("0 argument\n"); +} + +fun void test(int a) +{ + puts("1 argument\n"); +} + +fun void test(int a, int b, int c) +{ + puts("3 argument\n"); +} + +fun int main() +{ + test(); + test(1); + test(1,2); + test(1,2,3); + getchar(); + return 0; +} \ No newline at end of file diff --git a/tests/Vectors/project.jp b/tests/Vectors/project.jp new file mode 100644 index 0000000..7eb629b --- /dev/null +++ b/tests/Vectors/project.jp @@ -0,0 +1,9 @@ +bin: vectors +requires: JetCore +files: test.jet +libs: "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\msvcrt.lib" "C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86\kernel32.lib" + +[debug] +prebuild: "echo Hello im prebuild" +postbuild: "echo build is complete hi im debug" +config: "--linker ld" \ No newline at end of file diff --git a/tests/Vectors/test.jet b/tests/Vectors/test.jet new file mode 100644 index 0000000..1dc2927 --- /dev/null +++ b/tests/Vectors/test.jet @@ -0,0 +1,199 @@ + +extern fun int printf(char* h, int h); +extern fun char* malloc(int x); + +extern fun int puts(char* str); + +extern fun char getchar(); + +/*struct function +{ + T ptr; + char data[64]; +} + +trait Any +{ +} + +trait IEnumerator +{ + fun TT Current(); + + fun void Reset(); + fun bool MoveNext(); +} + +trait IEnumerable +{ + fun IEnumerator GetEnumerator(); +} + +fun void IEnumerable::Print() +{ + let enumer = this->GetEnumerator(); + while (enumer.MoveNext())// == 1) + { + puts("Got one!"); + } +}*/ + +fun void IEnumerator::Test() +{ + while (this->MoveNext())// == 1) + { + puts("testing"); + printf("Number %i\n", this->Current()); + } +} + +generator int test(char qp) +{ + let short y = 7; + for (let q = 10; q < 15; q++) + { + yield q; + } + + //puts("one"); + yield y; + //puts("two"); + yield qp; + //puts("three"); + yield 3; +} + +generator int power(int number, int exponent) +{ + let result = 1; + for (let i = 0; i < exponent; i++) + { + result = result * number; + yield result; + } +} + +/*struct WhereIterable +{ + Base* iterable; + function fn; + + fun WhereIterator> GetEnumerator() + { + let WhereIterator> x; + x.iter = this->iterable->GetEnumerator(); + x.fn = this->fn; + return x; + } +} + +struct WhereIterator +{ + Base iter; + function fn; + + fun T Current() + { + return this->iter.Current(); + } + + fun void Reset() + { + this->iter.Reset(); + } + + fun int MoveNext() + { + while (this->iter.MoveNext()) + { + let fn = this->fn; + if (fn(this->iter.Current())) + return 1; + } + return 0; + } +}*/ + +fun WhereIterable IEnumerable::Where(function fn) +{ + let WhereIterable x; + x.iterable = this; + x.fn = fn; + return x; +} + +struct testv +{ + int i[20]; +} + +fun testv RetTest(int i) +{ + let testv t; + return t; +} + +struct qqq +{ + +fun testv RetTest(testv i) +{ + let testv t; + return t; +} +} + +fun int main() +{ + /*let x = power(2, 20); + let p = 0; + while (x.MoveNext()) + { + p = x.Current(); + printf("%i\n", x.Current()); + } + if (p != 1048576) + puts("fail"); + else + puts("pass"); + x.Reset(); + let vector tt; + let i = 0; + while (x.MoveNext()) + { + p = x.Current(); + tt.push_back(p); + printf("Number %i\n", x.Current()); + i++; + } + + if (i != tt.size()) + { + puts("fail"); + } + x.Reset(); + x.Test(); + x.Test();*/ + + //let iter = tt.GetEnumerator(); + //iter.Test(); + + let ppx = RetTest(5); + + let qqq jk; + let testv qqqq; + let psada = jk.RetTest(qqqq); + + //let fn = [](int x) -> bool { return x > 4000; }; + //if (fn(5)) + // puts("fail"); + + getchar(); + + //let where = tt.Where(fn); + //where.Test(); + + getchar(); + + return 0; +} \ No newline at end of file