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(".");
|
||||
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);
|
||||
Ast_Atom *atom = (Ast_Atom *)node->left;
|
||||
assert(is_atom(atom));
|
||||
@@ -274,6 +274,12 @@ gen_ast(Ast *ast){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(BINARY,Binary){
|
||||
gen_expr(node);
|
||||
gen(";");
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(FOR, For){
|
||||
gen("for(");
|
||||
if(node->init) gen_expr(node->init);
|
||||
@@ -391,10 +397,16 @@ compile_string(String filecontent, String filename = "default_name"_s){
|
||||
ctx.init(scratch, &heap);
|
||||
pctx = &ctx;
|
||||
|
||||
F64 tokenize_begin = os_time();
|
||||
lex_restream(&ctx, filecontent, filename);
|
||||
F64 tokenize_end = os_time();
|
||||
|
||||
F64 parse_begin = os_time();
|
||||
Ast_Package *result = parse_file();
|
||||
sym_insert_builtins();
|
||||
pctx->resolving_package = result;
|
||||
F64 parse_end = os_time();
|
||||
|
||||
|
||||
gen(R"==(
|
||||
//-------------------------------
|
||||
@@ -403,12 +415,28 @@ compile_string(String filecontent, String filename = "default_name"_s){
|
||||
//-------------------------------
|
||||
)==");
|
||||
|
||||
F64 resolve_begin = os_time();
|
||||
resolve_package(result);
|
||||
// eval_decl(result);
|
||||
F64 resolve_end = os_time();
|
||||
|
||||
F64 codegen_begin = os_time();
|
||||
gen_ast(result);
|
||||
F64 codegen_end = os_time();
|
||||
|
||||
exp_destroy(&heap);
|
||||
|
||||
F64 flattening_begin = os_time();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
4
main.cpp
4
main.cpp
@@ -32,9 +32,9 @@ For now I don't thing it should be overloadable.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@todo
|
||||
[ ] - Init statements
|
||||
[ ] - More operators
|
||||
[ ] - Init statements, different kinds [+=] [-=] etc.
|
||||
[ ] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
|
||||
[ ] - More operators
|
||||
[ ] - 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
|
||||
|
||||
@@ -132,7 +132,8 @@ struct Lexer{
|
||||
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
|
||||
lexc(Lex_Stream *s){
|
||||
@@ -353,6 +354,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
lex_advance(s);
|
||||
}
|
||||
}
|
||||
else goto indent_loop_break;
|
||||
} break;
|
||||
|
||||
// @todo: add [;;] operator which adds new scope
|
||||
|
||||
@@ -79,6 +79,17 @@ token_match(Token_Kind kind){
|
||||
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 *
|
||||
token_match_keyword(Intern_String string){
|
||||
Token *token = token_get();
|
||||
@@ -145,6 +156,7 @@ parse_init_stmt(Ast_Expr *expr){
|
||||
result->flags = set_flag(result->flags, AST_STMT);
|
||||
return result;
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -264,9 +276,15 @@ parse_block(){
|
||||
|
||||
}
|
||||
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);
|
||||
else parsing_error(token, "Unexpected token [%s] while parsing statement", token_kind_string(token->kind).str);
|
||||
|
||||
}
|
||||
} while(token_match(SAME_SCOPE));
|
||||
token_expect(CLOSE_SCOPE);
|
||||
@@ -474,17 +492,24 @@ parse_enum(Token *pos){
|
||||
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 *
|
||||
parse_named(B32 is_global){
|
||||
Ast_Named *result = 0;
|
||||
if(is_global) token_match(SAME_SCOPE);
|
||||
if(token_is(TK_Identifier)){
|
||||
if(is_global && pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented");
|
||||
Token *name = token_next();
|
||||
if(is_global) {
|
||||
token_match(SAME_SCOPE);
|
||||
if(pctx->indent != 0){
|
||||
parsing_error(token_get(), "Top level declarations shouldn't be indented");
|
||||
}
|
||||
}
|
||||
|
||||
// @note: parse constant
|
||||
if(token_match(TK_DoubleColon)){
|
||||
// parse struct binding
|
||||
Token *name = token_get();
|
||||
if(token_match(TK_Identifier, TK_DoubleColon)){
|
||||
// @note parse struct binding
|
||||
Token *struct_pos = token_get();
|
||||
if(token_match_keyword(keyword_struct)){
|
||||
Ast_Struct *struct_val = parse_struct(struct_pos);
|
||||
@@ -496,36 +521,28 @@ parse_named(B32 is_global){
|
||||
result = ast_const(name, name->intern_val, (Ast_Expr *)enum_val);
|
||||
}
|
||||
|
||||
// parse constant expression
|
||||
// @note parse constant expression
|
||||
else{
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_const(name, name->intern_val, expr);
|
||||
}
|
||||
}
|
||||
|
||||
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)){
|
||||
else if(token_match(TK_Identifier, TK_Colon)){
|
||||
Ast_Expr *typespec = typespec = parse_expr();
|
||||
Ast_Expr *expr = parse_assign_expr();
|
||||
result = ast_var(name, typespec, name->intern_val, expr);
|
||||
}
|
||||
else{
|
||||
Token *token = token_get();
|
||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
||||
}
|
||||
}
|
||||
else if(!token_is(TK_End)){
|
||||
if(is_global){
|
||||
Token *token = token_get();
|
||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,15 @@ pointer := &with_type
|
||||
deref := *pointer
|
||||
|
||||
|
||||
test_stmts :: ()
|
||||
i := 0
|
||||
i += 4
|
||||
i -= 1
|
||||
i *= 2
|
||||
i /= 2
|
||||
i %= 2
|
||||
|
||||
|
||||
/*
|
||||
for
|
||||
pass
|
||||
|
||||
@@ -64,17 +64,22 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||
}
|
||||
|
||||
CASE(BINARY, Binary){
|
||||
switch(node->op){
|
||||
case TK_ColonAssign:{
|
||||
if(node->op == TK_ColonAssign){
|
||||
// Operand left = resolve_expr(node->left); // needs to be lvalue
|
||||
Operand right = resolve_expr(node->right);
|
||||
assert(node->left->kind == AST_IDENT);
|
||||
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_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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user