Cleanup
This commit is contained in:
11
main.cpp
11
main.cpp
@@ -32,15 +32,14 @@ For now I don't thing it should be overloadable.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@todo
|
||||
[ ] - For loop
|
||||
[ ] - Pass statement
|
||||
[ ] - More operators
|
||||
[ ] - Init statements
|
||||
[ ] - More operators
|
||||
[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
||||
[ ] - More for loop variations
|
||||
[ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree
|
||||
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
||||
[ ] - Write up on order independent declarations
|
||||
[ ] - Switch
|
||||
[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
||||
[ ] - More basic types
|
||||
[ ] - Array of inferred size
|
||||
[ ] - Lexer: Need to insert scope endings when hitting End of file
|
||||
@@ -52,10 +51,12 @@ For now I don't thing it should be overloadable.
|
||||
@donzo
|
||||
[x] - Access through struct names to constants Arena.CONSTANT
|
||||
[x] - Enums
|
||||
[x] - Initial for loop
|
||||
[x] - Enum . access to values
|
||||
[x] - Struct calls
|
||||
[x] - Default values in calls
|
||||
[x] - Resolving calls with default values
|
||||
[x] - Pass statement
|
||||
[x] - Resolving calls with named args, with indexed args
|
||||
[x] - Structs
|
||||
[x] - Struct field access
|
||||
@@ -63,7 +64,6 @@ For now I don't thing it should be overloadable.
|
||||
[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"
|
||||
@@ -85,7 +85,6 @@ int main(){
|
||||
test_array();
|
||||
test_string_builder();
|
||||
test_intern_table();
|
||||
lex_test();
|
||||
|
||||
String result = {};
|
||||
result = compile_file("globals.kl"_s);
|
||||
|
||||
12
new_ast.cpp
12
new_ast.cpp
@@ -271,22 +271,22 @@ struct Ast_Package:Ast{
|
||||
result->id = ++pctx->unique_ids
|
||||
|
||||
function Ast_Atom *
|
||||
ast_str(Token *pos, Intern_String string, Ast_Flag flags = 0){
|
||||
AST_NEW(Atom, STR, pos, AST_ATOM | flags);
|
||||
ast_str(Token *pos, Intern_String string){
|
||||
AST_NEW(Atom, STR, pos, AST_ATOM | AST_EXPR);
|
||||
result->intern_val = string;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Atom *
|
||||
ast_ident(Token *pos, Intern_String string, Ast_Flag flags = 0){
|
||||
AST_NEW(Atom, IDENT, pos, AST_ATOM | flags);
|
||||
ast_ident(Token *pos, Intern_String string){
|
||||
AST_NEW(Atom, IDENT, pos, AST_ATOM | AST_EXPR);
|
||||
result->intern_val = string;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Atom *
|
||||
ast_int(Token *pos, S64 integer, Ast_Flag flags = 0){
|
||||
AST_NEW(Atom, INT, pos, AST_ATOM | flags);
|
||||
ast_int(Token *pos, S64 integer){
|
||||
AST_NEW(Atom, INT, pos, AST_ATOM | AST_EXPR);
|
||||
result->int_val = integer;
|
||||
return result;
|
||||
}
|
||||
|
||||
61
new_lex.cpp
61
new_lex.cpp
@@ -51,6 +51,7 @@ enum Token_Kind{
|
||||
TK_Colon,
|
||||
|
||||
TK_Assign,
|
||||
TK_ColonAssign,
|
||||
TK_DivAssign,
|
||||
TK_MulAssign,
|
||||
TK_ModAssign,
|
||||
@@ -131,6 +132,8 @@ struct Lexer{
|
||||
S64 token_iter;
|
||||
};
|
||||
|
||||
force_inline B32 token_is_assign(Token *token){return token->kind >= TK_FirstAssign && token->kind <= TK_LastAssign;}
|
||||
|
||||
function U8
|
||||
lexc(Lex_Stream *s){
|
||||
return s->stream.str[s->iter];
|
||||
@@ -507,6 +510,10 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
lex_advance(s);
|
||||
t.kind = TK_DoubleColon;
|
||||
}
|
||||
else if(lexc(s) == '='){
|
||||
lex_advance(s);
|
||||
t.kind = TK_ColonAssign;
|
||||
}
|
||||
else {
|
||||
t.kind = TK_Colon;
|
||||
}
|
||||
@@ -630,59 +637,6 @@ lex_stream(Allocator *token_string_arena, Allocator *map_allocator, String istre
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
lex_test(){
|
||||
Scratch scratch;
|
||||
String test = "Keyword //R\n 18446744073709551616\n {}\n)(@?&+-....->,:::/**/\"Thing\" Thingy"
|
||||
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
||||
"for if while switch :="_s;
|
||||
|
||||
Array<String> keywords = {scratch};
|
||||
keywords.add("Keyword"_s);
|
||||
keywords.add("for"_s);
|
||||
keywords.add("if"_s);
|
||||
keywords.add("while"_s);
|
||||
keywords.add("switch"_s);
|
||||
|
||||
Lexer lexer = lex_make(scratch, scratch);
|
||||
lex_set_keywords(&lexer, keywords);
|
||||
lex_restream(&lexer, test, "Test1"_s);
|
||||
Array<Token> arr = lexer.tokens;
|
||||
|
||||
Token_Kind kind[] = {
|
||||
SAME_SCOPE,
|
||||
TK_Keyword, OPEN_SCOPE, TK_Error, OPEN_SCOPE, TK_OpenBrace,TK_CloseBrace,CLOSE_SCOPE, CLOSE_SCOPE, SAME_SCOPE, TK_CloseParen,TK_OpenParen,
|
||||
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,
|
||||
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
|
||||
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
|
||||
TK_Equals, TK_Integer, TK_Integer, TK_Integer,
|
||||
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
|
||||
TK_Colon, TK_Assign, TK_End
|
||||
};
|
||||
String strs[] = {
|
||||
""_s, "Keyword"_s, ""_s, "18446744073709551616"_s, ""_s, "{"_s,"}"_s, ""_s, ""_s, ""_s, ")"_s, "("_s,
|
||||
"@"_s,"?"_s,"&"_s,"+"_s,"-"_s,
|
||||
"..."_s,"."_s,"->"_s,","_s,"::"_s,":"_s,
|
||||
"Thing"_s,"Thingy"_s,"Test_Meme"_s, "+="_s,"-="_s,
|
||||
"=="_s,"42524"_s,"4294967295"_s,"18446744073709551615"_s,
|
||||
"for"_s, "if"_s, "while"_s, "switch"_s, ":"_s, "="_s, ""_s,
|
||||
};
|
||||
U64 vals[] = {
|
||||
42524, 4294967295, 18446744073709551615llu
|
||||
};
|
||||
|
||||
int ui = 0;
|
||||
S32 i = 0;
|
||||
For(arr){
|
||||
assert(it.kind == kind[i]);
|
||||
assert(string_compare(it.string, strs[i]));
|
||||
if(it.kind == TK_Integer){
|
||||
assert(it.int_val == vals[ui++]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Token metadata
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -706,6 +660,7 @@ token_kind_string(Token_Kind kind){
|
||||
case TK_CloseBrace: return "}"_s;
|
||||
case TK_OpenBracket: return "["_s;
|
||||
case TK_CloseBracket: return "]"_s;
|
||||
case TK_ColonAssign: return ":="_s;
|
||||
case TK_Comma: return ","_s;
|
||||
case TK_Pound: return "#"_s;
|
||||
case TK_Question: return "?"_s;
|
||||
|
||||
@@ -138,15 +138,13 @@ function Ast_Expr *parse_expr(S64 rbp = 0);
|
||||
function Ast_Expr *
|
||||
parse_init_stmt(Ast_Expr *expr){
|
||||
Token *token = token_get();
|
||||
if(token_match(TK_Colon)){
|
||||
if(expr->kind != AST_IDENT) parsing_error(token, "Failed to parse init stmt, expected left of [:] to be a token of kind [Identifier]");
|
||||
if(token_match(TK_Assign)){
|
||||
if(token_is_assign(token)){
|
||||
token_next();
|
||||
Ast_Expr *value = parse_expr();
|
||||
Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token);
|
||||
result->flags = set_flag(result->flags, AST_STMT);
|
||||
return result;
|
||||
}
|
||||
else not_implemented;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -311,9 +309,9 @@ parse_lambda(Token *token, B32 is_typespec = false){
|
||||
function Ast_Expr *
|
||||
null_denotation(Token *token){
|
||||
switch(token->kind){
|
||||
case TK_StringLit : return ast_str(token, token->intern_val, AST_EXPR);
|
||||
case TK_Identifier : return ast_ident(token, token->intern_val, AST_EXPR);
|
||||
case TK_Integer : return ast_int(token, token->int_val, AST_EXPR);
|
||||
case TK_StringLit : return ast_str(token, token->intern_val);
|
||||
case TK_Identifier : return ast_ident(token, token->intern_val);
|
||||
case TK_Integer : return ast_int(token, token->int_val);
|
||||
case TK_Pointer : return ast_expr_unary(token, TK_Pointer, parse_expr());
|
||||
case TK_Dereference: return ast_expr_unary(token, TK_Dereference, parse_expr());
|
||||
|
||||
@@ -505,14 +503,15 @@ parse_named(B32 is_global){
|
||||
}
|
||||
}
|
||||
|
||||
else if(token_match(TK_ColonAssign)){
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_var(name, 0, name->intern_val, expr);
|
||||
}
|
||||
|
||||
// @note: parse variable
|
||||
else if(token_match(TK_Colon)){
|
||||
Ast_Expr *typespec = 0;
|
||||
Ast_Expr *expr = 0;
|
||||
if(!token_is(TK_Assign)) typespec = parse_expr();
|
||||
if(token_match(TK_Assign)) expr = parse_expr();
|
||||
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
|
||||
|
||||
Ast_Expr *typespec = typespec = parse_expr();
|
||||
Ast_Expr *expr = parse_assign_expr();
|
||||
result = ast_var(name, typespec, name->intern_val, expr);
|
||||
}
|
||||
else{
|
||||
|
||||
154
typecheck.cpp
154
typecheck.cpp
@@ -65,7 +65,7 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||
|
||||
CASE(BINARY, Binary){
|
||||
switch(node->op){
|
||||
case TK_Colon:{
|
||||
case TK_ColonAssign:{
|
||||
// Operand left = resolve_expr(node->left); // needs to be lvalue
|
||||
Operand right = resolve_expr(node->right);
|
||||
assert(node->left->kind == AST_IDENT);
|
||||
@@ -134,9 +134,54 @@ _rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
||||
}
|
||||
#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym)
|
||||
|
||||
function Operand
|
||||
resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
|
||||
Scratch scratch;
|
||||
Ast_Resolved_Type *lambda_type = 0;
|
||||
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret);
|
||||
Array<Ast_Resolved_Type *> args = {scratch};
|
||||
For(lambda->args){
|
||||
Operand type = resolve_expr(it->typespec);
|
||||
if(type.type != type_type) parsing_error(it->pos, "Required expression of kind [type]");
|
||||
Operand default_value = resolve_expr(it->default_value, type.type_val);
|
||||
if(default_value.type && default_value.type != type.type_val) parsing_error(it->pos, "Default value type and type declaration differ");
|
||||
args.add(type.type_val);
|
||||
}
|
||||
|
||||
lambda_type = type_lambda(lambda, ret_type, args);
|
||||
sym_type(lambda, lambda_type);
|
||||
Operand result = operand_type(lambda_type);
|
||||
|
||||
// @note: top level lambda needs to get marked as resolved
|
||||
// so that the cyclic dependency wont trigger
|
||||
if(sym){
|
||||
sym->type = lambda_type;
|
||||
sym->state = SYM_RESOLVED;
|
||||
}
|
||||
|
||||
// @todo: We also need to make sure there is a return value when ret type is not void
|
||||
// @note: then try resolving the block of lambda
|
||||
if(lambda->block){
|
||||
S64 scope_index = scope_open();
|
||||
For(lambda->args){
|
||||
S64 i = lambda->args.get_index(&it);
|
||||
Ast_Resolved_Type *type = args[i];
|
||||
sym_insert(SYM_VAR, it->name, type, {}, it);
|
||||
}
|
||||
For(lambda->block->stmts){
|
||||
resolve_stmt(it, ret_type);
|
||||
}
|
||||
scope_close(scope_index);
|
||||
result.type = lambda_type;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function Operand
|
||||
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){
|
||||
if(!ast) return {}; // @todo: add option for better error prevention
|
||||
assert(is_flag_set(ast->flags, AST_EXPR));
|
||||
|
||||
switch(ast->kind){
|
||||
CASE(INT, Atom){
|
||||
@@ -188,70 +233,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(ENUM, Enum){
|
||||
Ast_Resolved_Type *type = type_enum(node);
|
||||
|
||||
S64 scope_index = scope_open();
|
||||
S64 value = 0;
|
||||
For(node->members){
|
||||
Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
|
||||
if(op.type){
|
||||
value = op.int_val + 1;
|
||||
}
|
||||
else{
|
||||
op.type = type_int;
|
||||
op.int_val = value++;
|
||||
}
|
||||
|
||||
sym_insert(SYM_CONST, it->name, op.type, op.value, it);
|
||||
}
|
||||
scope_close(scope_index);
|
||||
|
||||
return operand_type(type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(LAMBDA, Lambda){
|
||||
// @note: first resolve type of lambda so recursive lambdas work
|
||||
Scratch scratch;
|
||||
Ast_Resolved_Type *lambda_type = 0;
|
||||
Ast_Resolved_Type *ret_type = resolve_typespec(node->ret);
|
||||
Array<Ast_Resolved_Type *> args = {scratch};
|
||||
For(node->args){
|
||||
Operand type = resolve_expr(it->typespec);
|
||||
if(type.type != type_type) parsing_error(it->pos, "Required expression of kind [type]");
|
||||
Operand default_value = resolve_expr(it->default_value, type.type_val);
|
||||
if(default_value.type && default_value.type != type.type_val) parsing_error(it->pos, "Default value type and type declaration differ");
|
||||
args.add(type.type_val);
|
||||
}
|
||||
lambda_type = type_lambda(node, ret_type, args);
|
||||
{
|
||||
sym_type(node, lambda_type);
|
||||
if(lambda_to_resolve){
|
||||
lambda_to_resolve->type = lambda_type;
|
||||
lambda_to_resolve->state = SYM_RESOLVED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Operand result = operand_type(lambda_type);
|
||||
// @todo: We also need to make sure there is a return value when ret type is not void
|
||||
// @note: then try resolving the block of lambda
|
||||
if(node->block){
|
||||
S64 scope_index = scope_open();
|
||||
For(node->args){
|
||||
S64 i = node->args.get_index(&it);
|
||||
Ast_Resolved_Type *type = args[i];
|
||||
sym_insert(SYM_VAR, it->name, type, {}, it);
|
||||
}
|
||||
For(node->block->stmts){
|
||||
resolve_stmt(it, ret_type);
|
||||
}
|
||||
scope_close(scope_index);
|
||||
result.type = lambda_type;
|
||||
}
|
||||
|
||||
return result;
|
||||
return resolve_lambda(node);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
@@ -544,22 +527,53 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
BREAK();
|
||||
}
|
||||
|
||||
invalid_default_case;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function Operand
|
||||
resolve_const(Ast_Expr *ast, Sym *sym){
|
||||
switch(ast->kind){
|
||||
CASE(LAMBDA, Lambda){
|
||||
return resolve_lambda(node, sym);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(ENUM, Enum){
|
||||
Ast_Resolved_Type *type = type_enum(node);
|
||||
S64 scope_index = scope_open();
|
||||
S64 value = 0;
|
||||
For(node->members){
|
||||
Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
|
||||
if(op.type){
|
||||
value = op.int_val + 1;
|
||||
}
|
||||
else{
|
||||
op.type = type_int;
|
||||
op.int_val = value++;
|
||||
}
|
||||
|
||||
sym_insert(SYM_CONST, it->name, op.type, op.value, it);
|
||||
}
|
||||
scope_close(scope_index);
|
||||
return operand_type(type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(STRUCT, Struct){
|
||||
Ast_Resolved_Type *type = type_struct(node);
|
||||
return operand_type(type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
|
||||
invalid_default_case;
|
||||
default: return resolve_expr(ast, 0, sym);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function Operand
|
||||
@@ -575,7 +589,7 @@ resolve_binding(Ast *ast, Sym *sym){
|
||||
}
|
||||
|
||||
CASE(CONST, Const){
|
||||
Operand expr = resolve_expr((Ast_Expr *)node->value, 0, sym);
|
||||
Operand expr = resolve_const((Ast_Expr *)node->value, sym);
|
||||
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
||||
assert(expr.type);
|
||||
return expr;
|
||||
|
||||
Reference in New Issue
Block a user