This commit is contained in:
Krzosa Karol
2022-05-31 22:52:56 +02:00
parent 7ea0dfc7a6
commit 98d2389c9f
5 changed files with 119 additions and 152 deletions

View File

@@ -32,15 +32,14 @@ For now I don't thing it should be overloadable.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@todo @todo
[ ] - For loop
[ ] - Pass statement
[ ] - More operators
[ ] - Init statements [ ] - 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 [ ] - 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 [ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
[ ] - Write up on order independent declarations [ ] - Write up on order independent declarations
[ ] - Switch [ ] - Switch
[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
[ ] - More basic types [ ] - More basic types
[ ] - Array of inferred size [ ] - Array of inferred size
[ ] - Lexer: Need to insert scope endings when hitting End of file [ ] - 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 @donzo
[x] - Access through struct names to constants Arena.CONSTANT [x] - Access through struct names to constants Arena.CONSTANT
[x] - Enums [x] - Enums
[x] - Initial for loop
[x] - Enum . access to values [x] - Enum . access to values
[x] - Struct calls [x] - Struct calls
[x] - Default values in calls [x] - Default values in calls
[x] - Resolving calls with default values [x] - Resolving calls with default values
[x] - Pass statement
[x] - Resolving calls with named args, with indexed args [x] - Resolving calls with named args, with indexed args
[x] - Structs [x] - Structs
[x] - Struct field access [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] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int
[x] - Initial order independence algorithm [x] - Initial order independence algorithm
[x] - Think about compound expressions, unify with calls - maybe Thing(a=1) instead of Thing{a=1} [x] - Think about compound expressions, unify with calls - maybe Thing(a=1) instead of Thing{a=1}
*/ */
#include "base.cpp" #include "base.cpp"
@@ -85,7 +85,6 @@ int main(){
test_array(); test_array();
test_string_builder(); test_string_builder();
test_intern_table(); test_intern_table();
lex_test();
String result = {}; String result = {};
result = compile_file("globals.kl"_s); result = compile_file("globals.kl"_s);

View File

@@ -271,22 +271,22 @@ struct Ast_Package:Ast{
result->id = ++pctx->unique_ids result->id = ++pctx->unique_ids
function Ast_Atom * function Ast_Atom *
ast_str(Token *pos, Intern_String string, Ast_Flag flags = 0){ ast_str(Token *pos, Intern_String string){
AST_NEW(Atom, STR, pos, AST_ATOM | flags); AST_NEW(Atom, STR, pos, AST_ATOM | AST_EXPR);
result->intern_val = string; result->intern_val = string;
return result; return result;
} }
function Ast_Atom * function Ast_Atom *
ast_ident(Token *pos, Intern_String string, Ast_Flag flags = 0){ ast_ident(Token *pos, Intern_String string){
AST_NEW(Atom, IDENT, pos, AST_ATOM | flags); AST_NEW(Atom, IDENT, pos, AST_ATOM | AST_EXPR);
result->intern_val = string; result->intern_val = string;
return result; return result;
} }
function Ast_Atom * function Ast_Atom *
ast_int(Token *pos, S64 integer, Ast_Flag flags = 0){ ast_int(Token *pos, S64 integer){
AST_NEW(Atom, INT, pos, AST_ATOM | flags); AST_NEW(Atom, INT, pos, AST_ATOM | AST_EXPR);
result->int_val = integer; result->int_val = integer;
return result; return result;
} }

View File

@@ -51,6 +51,7 @@ enum Token_Kind{
TK_Colon, TK_Colon,
TK_Assign, TK_Assign,
TK_ColonAssign,
TK_DivAssign, TK_DivAssign,
TK_MulAssign, TK_MulAssign,
TK_ModAssign, TK_ModAssign,
@@ -131,6 +132,8 @@ struct Lexer{
S64 token_iter; S64 token_iter;
}; };
force_inline B32 token_is_assign(Token *token){return token->kind >= TK_FirstAssign && token->kind <= TK_LastAssign;}
function U8 function U8
lexc(Lex_Stream *s){ lexc(Lex_Stream *s){
return s->stream.str[s->iter]; return s->stream.str[s->iter];
@@ -507,6 +510,10 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
lex_advance(s); lex_advance(s);
t.kind = TK_DoubleColon; t.kind = TK_DoubleColon;
} }
else if(lexc(s) == '='){
lex_advance(s);
t.kind = TK_ColonAssign;
}
else { else {
t.kind = TK_Colon; t.kind = TK_Colon;
} }
@@ -630,59 +637,6 @@ lex_stream(Allocator *token_string_arena, Allocator *map_allocator, String istre
return result; 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 // Token metadata
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -706,6 +660,7 @@ token_kind_string(Token_Kind kind){
case TK_CloseBrace: return "}"_s; case TK_CloseBrace: return "}"_s;
case TK_OpenBracket: return "["_s; case TK_OpenBracket: return "["_s;
case TK_CloseBracket: return "]"_s; case TK_CloseBracket: return "]"_s;
case TK_ColonAssign: return ":="_s;
case TK_Comma: return ","_s; case TK_Comma: return ","_s;
case TK_Pound: return "#"_s; case TK_Pound: return "#"_s;
case TK_Question: return "?"_s; case TK_Question: return "?"_s;

View File

@@ -138,14 +138,12 @@ function Ast_Expr *parse_expr(S64 rbp = 0);
function Ast_Expr * function Ast_Expr *
parse_init_stmt(Ast_Expr *expr){ parse_init_stmt(Ast_Expr *expr){
Token *token = token_get(); Token *token = token_get();
if(token_match(TK_Colon)){ if(token_is_assign(token)){
if(expr->kind != AST_IDENT) parsing_error(token, "Failed to parse init stmt, expected left of [:] to be a token of kind [Identifier]"); token_next();
if(token_match(TK_Assign)){ Ast_Expr *value = parse_expr();
Ast_Expr *value = parse_expr(); Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token);
Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token); result->flags = set_flag(result->flags, AST_STMT);
return result; return result;
}
else not_implemented;
} }
return 0; return 0;
} }
@@ -311,9 +309,9 @@ parse_lambda(Token *token, B32 is_typespec = false){
function Ast_Expr * function Ast_Expr *
null_denotation(Token *token){ null_denotation(Token *token){
switch(token->kind){ switch(token->kind){
case TK_StringLit : return ast_str(token, token->intern_val, AST_EXPR); case TK_StringLit : return ast_str(token, token->intern_val);
case TK_Identifier : return ast_ident(token, token->intern_val, AST_EXPR); case TK_Identifier : return ast_ident(token, token->intern_val);
case TK_Integer : return ast_int(token, token->int_val, AST_EXPR); case TK_Integer : return ast_int(token, token->int_val);
case TK_Pointer : return ast_expr_unary(token, TK_Pointer, parse_expr()); case TK_Pointer : return ast_expr_unary(token, TK_Pointer, parse_expr());
case TK_Dereference: return ast_expr_unary(token, TK_Dereference, 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 // @note: parse variable
else if(token_match(TK_Colon)){ else if(token_match(TK_Colon)){
Ast_Expr *typespec = 0; Ast_Expr *typespec = typespec = parse_expr();
Ast_Expr *expr = 0; Ast_Expr *expr = parse_assign_expr();
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");
result = ast_var(name, typespec, name->intern_val, expr); result = ast_var(name, typespec, name->intern_val, expr);
} }
else{ else{

View File

@@ -65,7 +65,7 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
CASE(BINARY, Binary){ CASE(BINARY, Binary){
switch(node->op){ switch(node->op){
case TK_Colon:{ case TK_ColonAssign:{
// Operand left = resolve_expr(node->left); // needs to be lvalue // Operand left = resolve_expr(node->left); // needs to be lvalue
Operand right = resolve_expr(node->right); Operand right = resolve_expr(node->right);
assert(node->left->kind == AST_IDENT); 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) #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 function Operand
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){
if(!ast) return {}; // @todo: add option for better error prevention if(!ast) return {}; // @todo: add option for better error prevention
assert(is_flag_set(ast->flags, AST_EXPR));
switch(ast->kind){ switch(ast->kind){
CASE(INT, Atom){ CASE(INT, Atom){
@@ -188,70 +233,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
BREAK(); 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){ CASE(LAMBDA, Lambda){
// @note: first resolve type of lambda so recursive lambdas work return resolve_lambda(node);
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;
BREAK(); BREAK();
} }
@@ -544,22 +527,53 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
} }
} }
return result; return result;
BREAK(); 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){ CASE(STRUCT, Struct){
Ast_Resolved_Type *type = type_struct(node); Ast_Resolved_Type *type = type_struct(node);
return operand_type(type); return operand_type(type);
BREAK(); BREAK();
} }
default: return resolve_expr(ast, 0, sym);
invalid_default_case;
} }
return {};
} }
function Operand function Operand
@@ -575,7 +589,7 @@ resolve_binding(Ast *ast, Sym *sym){
} }
CASE(CONST, Const){ 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"); if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
assert(expr.type); assert(expr.type);
return expr; return expr;