257 lines
10 KiB
C++
257 lines
10 KiB
C++
/*
|
|
-------------------------------------------------------------------------------
|
|
|
|
2022.05.28 - On lambda expressions
|
|
I think it's not wise to add the multiline lambda expressions
|
|
As is the case with python it would require new alternative syntax.
|
|
The idea was to imply that the whitespace significant syntax is just
|
|
inserting '{' '}' ';' automatically and if you decide to write a brace
|
|
it stops being whitespace significant and you can type everything with semicolons and braces
|
|
Problem is first of all it's kind of weird to have a completly different syntax
|
|
in a language to solve something that is a minor inconvenience,
|
|
second of all it turned out to be kind of bad, maybe if it would be more
|
|
complicated then it would be ok but it implies that you have to semicolon end
|
|
a lot of thing unintuitively.
|
|
|
|
Probably single line lambdas should be ok. Currently braces turn off indentation
|
|
awareness. There might be something you can do by trying to turn that on
|
|
problem is that complicates parsing a lot cause you have to account for multiple
|
|
indent styles, which means error messages become bad.
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
2022.05.30 - On constructors and compound expressions
|
|
I unified the compound expression syntax (Type){} with function call syntax Type().
|
|
It's differentiating on whether you used type. I think there is a benefit to the language
|
|
not having an idea of overloading the type constructor. You will always know what will happen.
|
|
Unlike C++ for example. It seems like a minefield that can fuck your mind up. So many corner cases
|
|
and variants. having the idea of compounds doing one thing is reassuring I think.
|
|
You can always do a constructor by writing a function with lower case type if you want that.
|
|
For now I don't thing it should be overloadable.
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
We compile lot's of files, we keep track of them in Parse_Ctx, making sure we don't
|
|
parse same thing twice. Files belong to a module, files can be loaded #load "file".
|
|
All the files see all the decls from all the files in that module. We can import
|
|
other modules using a different directive #import. #import perhaps should be lazily
|
|
evaluated, making sure we don't resolve stuff we don't require. Currently probably
|
|
want to export all the symbols, we can namespace them optionally.
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
@todo
|
|
[ ] - Split Bc into builder and interpreter
|
|
[ ] - Implement functions
|
|
|
|
[ ] - Probably need to give Ast_Expr a Value field, then I can express Type nicely
|
|
[ ] - I would love for String, slice, Any etc. to have their struct declarations in source files, I also would want for stuff like string.str to work without weird special cases
|
|
[ ] - Var args with Any
|
|
|
|
[ ] - #test construct that would gather all tests and run them on start of program or something
|
|
[ ] - Foreign import that would link library
|
|
[ ] - Builtin dynamic arrays
|
|
[ ] - Kilobyte, Megabyte, Gigabyte
|
|
[ ] - Cast from array to pointer?
|
|
[ ] - Mixing loads and imports leads to code duplication, is that what we want???
|
|
[ ] - Fix field access, cant cast, cant index
|
|
[ ] - Add parent_scope to Ast_Type, Add name to Ast_Type?
|
|
[ ] - Some way to take slice of data
|
|
[ ] - Optional function renaming in codegen
|
|
[ ] - Using in structs to embed members, then casting offsets to that embedded member
|
|
[ ] - Type as a parameter to a function, alloc :: (size: U64, type: Type)
|
|
|
|
[ ] - Comma notation when declaring variables thing1, thing2: S32 :: probably want to unify it with var unpacking
|
|
[ ] - Add single line lambda expressions
|
|
[ ] - Ternary operator
|
|
[ ] - Disable ability to parse inner structs, functions, constants etc. ?
|
|
[ ] - Write up on order independent declarations
|
|
|
|
[ ] - Consider changing syntax of scopes to use braces { }
|
|
[ ] - Order independent declarations in structs ?
|
|
[ ] - constructor => thing :: (i: S32) -> {i = i, thing = 10}
|
|
[ ] - Casting to basic types by call S64(x)
|
|
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
|
|
|
@ideas
|
|
[ ] - Var args using Any array - args: []Any - delete vargs
|
|
[ ] - [Using] keyword that brings in the struct enviroment into current scope etc.
|
|
[ ] - Constant arrays that evaluate fully at compile time
|
|
[ ] - Rust like enum where you associate values(other structs) with keys
|
|
[ ] - Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {}
|
|
[ ] - Inject stack traces into the program
|
|
[ ] - Conditional compilation #if
|
|
[ ] - Polymorphism - create declaration of a polymorphic thing, when it's called just copy it, replace types and typecheck normally, when someone calls again you just search for the instantiation again
|
|
|
|
@donzo
|
|
[x] - Add token information to instructions
|
|
[x] - print those token lines nicely
|
|
[x] - Improve the python metaprogram
|
|
[x] - Implementing type Any
|
|
[x] - Runtime TypeInfo
|
|
[x] - Proper type Type support
|
|
[x] - Switch
|
|
[x] - Type aliases :: should probably be strictly typed, but assigning constant values should work
|
|
[x] - Array of inferred size
|
|
[x] - Casting pointers to and from void should be implicit
|
|
[x] - Multiple return values
|
|
[x] - Add c string
|
|
[-] - Should compound resolution use an algorithm to reorder compounds to initialize all fields in order
|
|
[x] - slices should be properly displayed in debugger
|
|
[x] - Imports inside of import shouldn't spill outside
|
|
[x] - Scope
|
|
[x] - #assert that handles constants at compile time and vars at runtime
|
|
[x] - Hex 0x42
|
|
[x] - Rewrite where # happen,
|
|
[x] - elif
|
|
[x] - cast ->
|
|
[x] - Remodel compound from call to {}
|
|
[x] - Fix codegen renames
|
|
[x] - Field access rewrite
|
|
[-] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix
|
|
[-] - Order independent constants in structs
|
|
[-] - Fix recursive lambdas in structs
|
|
[x] - Error message when file not found
|
|
[x] - Better error messages when type difference
|
|
[-] - Fixing access to functions/structs, in C we cant have functons inside of structs / functions so we need to rewrite the tree
|
|
[x] - Emitting #line
|
|
[x] - Making sure debugger works
|
|
[x] - We need ++ -- operators
|
|
[x] - Arrays with size passed
|
|
[x] - Values inited to 0 by default
|
|
[x] - Some way to call foreign functions
|
|
[x] - We are parsing wrong here: (t.str=(&string_to_lex.str)[i]);
|
|
[x] - Test new operators, add constant eval for them
|
|
[x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
|
[x] - Passing down program to compile through command line
|
|
[x] - More basic types
|
|
[x] - Implementing required operations int128
|
|
[x] - Fix casting
|
|
[x] - More for loop variations
|
|
[x] - Add basic support for floats
|
|
[x] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need big int
|
|
[x] - Add basic setup for new type system
|
|
[x] - Access through struct names to constants Arena.CONSTANT
|
|
[x] - Enums
|
|
[x] - Make sure pointer arithmetic works
|
|
[x] - Initial for loop
|
|
[x] - Enum . access to values
|
|
[x] - Character literal
|
|
[x] - Compiling and running a program
|
|
[x] - Infinite for loop
|
|
[x] - in new typesystem: Fix calls, fix all example programs
|
|
[x] - Fix arithmetic operations in new type system
|
|
[x] - Init statements, different kinds [+=] [-=] etc.
|
|
[x] - Struct calls
|
|
[x] - Operators: Bit negation, Not
|
|
[x] - Default values in calls
|
|
[x] - Resolving calls with default values
|
|
[x] - Pass statement
|
|
[x] - Lexer: Need to insert scope endings when hitting End of file
|
|
[x] - Resolving calls with named args, with indexed args
|
|
[x] - Structs
|
|
[x] - Struct field access
|
|
[x] - Struct field access with dots while compiling to arrows in c
|
|
[x] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int
|
|
[x] - Initial order independence algorithm
|
|
[x] - Think about compound expressions, unify with calls - maybe Thing(a=1) instead of Thing{a=1}
|
|
*/
|
|
|
|
#include "base.cpp"
|
|
#include "base_unicode.cpp"
|
|
#include "big_int_c3.cpp"
|
|
#include "compiler.h"
|
|
#include "lexing.cpp"
|
|
#include "types.h"
|
|
#include "ast.cpp"
|
|
#include "parsing.cpp"
|
|
#include "typechecking.h"
|
|
#include "typechecking.cpp"
|
|
|
|
#include "c_language_codegen.cpp"
|
|
#include "intermediate_representation.cpp"
|
|
// #include "bytecode_interpreter.cpp"
|
|
// #include "bytecode_codegen.cpp"
|
|
|
|
|
|
int main(int argument_count, char **arguments){
|
|
|
|
#if OS_WINDOWS
|
|
// Set output mode to handle virtual terminal sequences
|
|
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
if (hOut == INVALID_HANDLE_VALUE) {
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD dwMode = 0;
|
|
if (!GetConsoleMode(hOut, &dwMode)) {
|
|
return GetLastError();
|
|
}
|
|
|
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
if (!SetConsoleMode(hOut, dwMode)) {
|
|
return GetLastError();
|
|
}
|
|
#endif
|
|
|
|
test_os_memory();
|
|
thread_ctx_init();
|
|
test_unicode();
|
|
|
|
map_test();
|
|
test_array();
|
|
test_string_builder();
|
|
test_intern_table();
|
|
test_bucket_arrays();
|
|
|
|
emit_line_directives = true;
|
|
String program_name = "vm.kl"_s;
|
|
if(argument_count > 1){
|
|
program_name = string_from_cstring(arguments[1]);
|
|
}
|
|
|
|
F64 total_time = os_time();
|
|
begin_compilation();
|
|
|
|
{
|
|
Ast_Module *module = add_module(0, pctx->intern("language.kl"_s));
|
|
insert_builtin_types_into_scope(module);
|
|
pctx->language_base_module = module;
|
|
|
|
parse_all_modules();
|
|
resolve_everything_in_module(module);
|
|
// @note: language stuff needs to be declared before type_info data
|
|
// so we mark where it ends
|
|
pctx->base_language_ordered_decl_len = pctx->ordered_decls.len;
|
|
Ast_Decl *any_decl = search_for_decl(module, pctx->intern("Any"_s));
|
|
assert(any_decl->type == type_type);
|
|
type_any = any_decl->type_val;
|
|
}
|
|
|
|
|
|
Ast_Module *module = add_module(0, pctx->intern(program_name));
|
|
parse_all_modules();
|
|
assert(module);
|
|
resolve_everything_in_module(module);
|
|
|
|
|
|
arena_clear(&pctx->stage_arena);
|
|
// compile_to_bc();
|
|
// __debugbreak();
|
|
String result = get_compilation_result();
|
|
assert(os_write_file("program.c"_s, result));
|
|
{
|
|
Scratch scratch;
|
|
F64 begin = os_time();
|
|
String compiler_call = string_fmt(scratch, "clang.exe program.c -Wall -Wno-parentheses-equality -g -o a.exe -lgdi32 -luser32 -lwinmm");
|
|
system((const char *)compiler_call.str);
|
|
printf("\nclang = %f", os_time() - begin);
|
|
}
|
|
|
|
printf("\ntotal = %f", os_time() - total_time);
|
|
printf("\nparsing = %f", parsing_time_end - parsing_time_begin);
|
|
printf("\nresolving = %f", resolving_time_end - resolving_time_begin);
|
|
printf("\ngeneratin = %f", generating_time_end - generating_time_begin);
|
|
__debugbreak();
|
|
}
|