Basic variable reassignments
This commit is contained in:
32
ccodegen.cpp
32
ccodegen.cpp
@@ -108,7 +108,7 @@ gen_expr(Ast_Expr *ast){
|
|||||||
else gen(".");
|
else gen(".");
|
||||||
gen_expr(node->right);
|
gen_expr(node->right);
|
||||||
}
|
}
|
||||||
else if(node->op == TK_Colon){ // @todo: I think this needs to be a stmt
|
else if(node->op == TK_ColonAssign){ // @todo: I think this needs to be a stmt
|
||||||
Sym *sym = resolved_get(node);
|
Sym *sym = resolved_get(node);
|
||||||
Ast_Atom *atom = (Ast_Atom *)node->left;
|
Ast_Atom *atom = (Ast_Atom *)node->left;
|
||||||
assert(is_atom(atom));
|
assert(is_atom(atom));
|
||||||
@@ -274,6 +274,12 @@ gen_ast(Ast *ast){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CASE(BINARY,Binary){
|
||||||
|
gen_expr(node);
|
||||||
|
gen(";");
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
CASE(FOR, For){
|
CASE(FOR, For){
|
||||||
gen("for(");
|
gen("for(");
|
||||||
if(node->init) gen_expr(node->init);
|
if(node->init) gen_expr(node->init);
|
||||||
@@ -391,10 +397,16 @@ compile_string(String filecontent, String filename = "default_name"_s){
|
|||||||
ctx.init(scratch, &heap);
|
ctx.init(scratch, &heap);
|
||||||
pctx = &ctx;
|
pctx = &ctx;
|
||||||
|
|
||||||
|
F64 tokenize_begin = os_time();
|
||||||
lex_restream(&ctx, filecontent, filename);
|
lex_restream(&ctx, filecontent, filename);
|
||||||
|
F64 tokenize_end = os_time();
|
||||||
|
|
||||||
|
F64 parse_begin = os_time();
|
||||||
Ast_Package *result = parse_file();
|
Ast_Package *result = parse_file();
|
||||||
sym_insert_builtins();
|
sym_insert_builtins();
|
||||||
pctx->resolving_package = result;
|
pctx->resolving_package = result;
|
||||||
|
F64 parse_end = os_time();
|
||||||
|
|
||||||
|
|
||||||
gen(R"==(
|
gen(R"==(
|
||||||
//-------------------------------
|
//-------------------------------
|
||||||
@@ -403,12 +415,28 @@ compile_string(String filecontent, String filename = "default_name"_s){
|
|||||||
//-------------------------------
|
//-------------------------------
|
||||||
)==");
|
)==");
|
||||||
|
|
||||||
|
F64 resolve_begin = os_time();
|
||||||
resolve_package(result);
|
resolve_package(result);
|
||||||
// eval_decl(result);
|
F64 resolve_end = os_time();
|
||||||
|
|
||||||
|
F64 codegen_begin = os_time();
|
||||||
gen_ast(result);
|
gen_ast(result);
|
||||||
|
F64 codegen_end = os_time();
|
||||||
|
|
||||||
exp_destroy(&heap);
|
exp_destroy(&heap);
|
||||||
|
|
||||||
|
F64 flattening_begin = os_time();
|
||||||
String string_result = string_flatten(scratch, &pctx->gen);
|
String string_result = string_flatten(scratch, &pctx->gen);
|
||||||
|
F64 flattening_end = os_time();
|
||||||
|
|
||||||
|
printf("\n//-------------------------------");
|
||||||
|
printf("\n// Tokenization: %f", tokenize_end - tokenize_begin);
|
||||||
|
printf("\n// Parsing : %f", parse_end - parse_begin);
|
||||||
|
printf("\n// Resolving : %f", resolve_end - resolve_begin);
|
||||||
|
printf("\n// Codegen : %f", codegen_end - codegen_begin);
|
||||||
|
printf("\n// Flattening : %f", flattening_end - flattening_begin);
|
||||||
|
printf("\n//-------------------------------");
|
||||||
|
|
||||||
return string_result;
|
return string_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
main.cpp
4
main.cpp
@@ -32,9 +32,9 @@ For now I don't thing it should be overloadable.
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@todo
|
@todo
|
||||||
[ ] - Init statements
|
[ ] - Init statements, different kinds [+=] [-=] etc.
|
||||||
[ ] - More operators
|
|
||||||
[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
||||||
|
[ ] - More operators
|
||||||
[ ] - More for loop variations
|
[ ] - 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
|
||||||
|
|||||||
@@ -132,7 +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;}
|
force_inline B32 token_is_assign(Token_Kind token){return token >= TK_FirstAssign && token <= TK_LastAssign;}
|
||||||
|
force_inline B32 token_is_assign(Token *token){return token_is_assign(token->kind);}
|
||||||
|
|
||||||
function U8
|
function U8
|
||||||
lexc(Lex_Stream *s){
|
lexc(Lex_Stream *s){
|
||||||
@@ -353,6 +354,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else goto indent_loop_break;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// @todo: add [;;] operator which adds new scope
|
// @todo: add [;;] operator which adds new scope
|
||||||
|
|||||||
@@ -79,6 +79,17 @@ token_match(Token_Kind kind){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Token *
|
||||||
|
token_match(Token_Kind a, Token_Kind b){
|
||||||
|
Token *ta = token_get();
|
||||||
|
Token *tb = token_get(1);
|
||||||
|
if(ta->kind == a && tb->kind == b){
|
||||||
|
token_next(); token_next();
|
||||||
|
return ta;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
function Token *
|
function Token *
|
||||||
token_match_keyword(Intern_String string){
|
token_match_keyword(Intern_String string){
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
@@ -145,6 +156,7 @@ parse_init_stmt(Ast_Expr *expr){
|
|||||||
result->flags = set_flag(result->flags, AST_STMT);
|
result->flags = set_flag(result->flags, AST_STMT);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,9 +276,15 @@ parse_block(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Ast_Named *result = parse_named(false);
|
Ast *result = parse_named(false);
|
||||||
|
if(!result){
|
||||||
|
result = parse_expr();
|
||||||
|
result = parse_init_stmt((Ast_Expr *)result);
|
||||||
|
}
|
||||||
|
|
||||||
if(result) stmts.add(result);
|
if(result) stmts.add(result);
|
||||||
else parsing_error(token, "Unexpected token [%s] while parsing statement", token_kind_string(token->kind).str);
|
else parsing_error(token, "Unexpected token [%s] while parsing statement", token_kind_string(token->kind).str);
|
||||||
|
|
||||||
}
|
}
|
||||||
} while(token_match(SAME_SCOPE));
|
} while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
@@ -474,58 +492,57 @@ parse_enum(Token *pos){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Needs peeking only because I didn't want to duplicate code
|
||||||
|
for parsing statements and it makes code nicer.
|
||||||
|
Statements can have named syntax i :=
|
||||||
|
*/
|
||||||
function Ast_Named *
|
function Ast_Named *
|
||||||
parse_named(B32 is_global){
|
parse_named(B32 is_global){
|
||||||
Ast_Named *result = 0;
|
Ast_Named *result = 0;
|
||||||
if(is_global) token_match(SAME_SCOPE);
|
if(is_global) {
|
||||||
if(token_is(TK_Identifier)){
|
token_match(SAME_SCOPE);
|
||||||
if(is_global && pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented");
|
if(pctx->indent != 0){
|
||||||
Token *name = token_next();
|
parsing_error(token_get(), "Top level declarations shouldn't be indented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @note: parse constant
|
Token *name = token_get();
|
||||||
if(token_match(TK_DoubleColon)){
|
if(token_match(TK_Identifier, TK_DoubleColon)){
|
||||||
// parse struct binding
|
// @note parse struct binding
|
||||||
Token *struct_pos = token_get();
|
Token *struct_pos = token_get();
|
||||||
if(token_match_keyword(keyword_struct)){
|
if(token_match_keyword(keyword_struct)){
|
||||||
Ast_Struct *struct_val = parse_struct(struct_pos);
|
Ast_Struct *struct_val = parse_struct(struct_pos);
|
||||||
result = ast_const(name, name->intern_val, (Ast_Expr *)struct_val);
|
result = ast_const(name, name->intern_val, (Ast_Expr *)struct_val);
|
||||||
}
|
|
||||||
|
|
||||||
else if(token_match_keyword(keyword_enum)){
|
|
||||||
Ast_Enum *enum_val = parse_enum(struct_pos);
|
|
||||||
result = ast_const(name, name->intern_val, (Ast_Expr *)enum_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse constant expression
|
|
||||||
else{
|
|
||||||
Ast_Expr *expr = parse_expr();
|
|
||||||
result = ast_const(name, name->intern_val, expr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(token_match(TK_ColonAssign)){
|
else if(token_match_keyword(keyword_enum)){
|
||||||
Ast_Expr *expr = parse_expr();
|
Ast_Enum *enum_val = parse_enum(struct_pos);
|
||||||
result = ast_var(name, 0, name->intern_val, expr);
|
result = ast_const(name, name->intern_val, (Ast_Expr *)enum_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note: parse variable
|
// @note parse constant expression
|
||||||
else if(token_match(TK_Colon)){
|
|
||||||
Ast_Expr *typespec = typespec = parse_expr();
|
|
||||||
Ast_Expr *expr = parse_assign_expr();
|
|
||||||
result = ast_var(name, typespec, name->intern_val, expr);
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
Token *token = token_get();
|
Ast_Expr *expr = parse_expr();
|
||||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
result = ast_const(name, name->intern_val, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!token_is(TK_End)){
|
else if(token_match(TK_Identifier, TK_Colon)){
|
||||||
if(is_global){
|
Ast_Expr *typespec = typespec = parse_expr();
|
||||||
Token *token = token_get();
|
Ast_Expr *expr = parse_assign_expr();
|
||||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
result = ast_var(name, typespec, name->intern_val, expr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if(token_match(TK_Identifier, TK_ColonAssign)){
|
||||||
|
Ast_Expr *expr = parse_expr();
|
||||||
|
result = ast_var(name, 0, name->intern_val, expr);
|
||||||
|
}
|
||||||
|
else if(is_global && name->kind != TK_End){
|
||||||
|
parsing_error(name, "Unexpected token: [%s] when parsing a declaration", token_kind_string(name->kind).str);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ pointer := &with_type
|
|||||||
deref := *pointer
|
deref := *pointer
|
||||||
|
|
||||||
|
|
||||||
|
test_stmts :: ()
|
||||||
|
i := 0
|
||||||
|
i += 4
|
||||||
|
i -= 1
|
||||||
|
i *= 2
|
||||||
|
i /= 2
|
||||||
|
i %= 2
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
for
|
for
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -64,17 +64,22 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(BINARY, Binary){
|
CASE(BINARY, Binary){
|
||||||
switch(node->op){
|
if(node->op == TK_ColonAssign){
|
||||||
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);
|
Ast_Atom *atom = (Ast_Atom *)node->left; // @todo use left operand
|
||||||
Ast_Atom *atom = (Ast_Atom *)node->left; // @todo use left operand
|
Sym *sym = sym_new_resolved(SYM_VAR, atom->intern_val, right.type, right.value, node);
|
||||||
Sym *sym = sym_new_resolved(SYM_VAR, atom->intern_val, right.type, right.value, node);
|
sym_insert(sym);
|
||||||
sym_insert(sym);
|
|
||||||
}break;
|
|
||||||
invalid_default_case;
|
|
||||||
}
|
}
|
||||||
|
else if(token_is_assign(node->op)){
|
||||||
|
// @todo: assign value to constant
|
||||||
|
// @todo: lvalue concept, passing down syms to change (constants)
|
||||||
|
Operand left = resolve_expr(node->left);
|
||||||
|
Operand right = resolve_expr(node->right);
|
||||||
|
if(left.type != right.type) parsing_error(node->pos, "Different types");
|
||||||
|
}
|
||||||
|
else invalid_codepath;
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user