Begin structs, add comment on multiline lambdas, add Ast flags

This commit is contained in:
Krzosa Karol
2022-05-29 11:29:26 +02:00
parent 7de941899f
commit 07b793aacc
7 changed files with 116 additions and 26 deletions

View File

@@ -245,8 +245,8 @@ gen_ast(Ast *ast){
Sym *sym = resolved_get(node); Sym *sym = resolved_get(node);
if(sym->type->kind == TYPE_Lambda){ if(sym->type->kind == TYPE_Lambda){
if(node->expr->kind == AST_LAMBDA){ if(node->value->kind == AST_LAMBDA){
Ast_Lambda *lambda = (Ast_Lambda *)node->expr; Ast_Lambda *lambda = (Ast_Lambda *)node->value;
gen("static "); gen("static ");
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret); Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
gen_simple_decl(ret, node->name); gen_simple_decl(ret, node->name);
@@ -267,7 +267,7 @@ gen_ast(Ast *ast){
else{ else{
gen_simple_decl(sym->type, node->name); gen_simple_decl(sym->type, node->name);
gen(" = "); gen(" = ");
gen_expr(node->expr); gen_expr((Ast_Expr *)node->value);
gen(";"); gen(";");
} }
} }

View File

@@ -7,8 +7,32 @@
#include "new_resolve.cpp" #include "new_resolve.cpp"
#include "ccodegen.cpp" #include "ccodegen.cpp"
// 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.
/// @todo /// @todo
/// [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
/// [ ] - Add single line lambda expressions/
/// [ ] - Think about compound expressions, unify with calls - maybe Thing(a=1) instead of Thing{a=1}
/// [ ] - Structs
/// [ ] - Enums
/// [ ] - For loop
/// [ ] - Switch
int main(){ int main(){
@@ -23,8 +47,8 @@ int main(){
test_intern_table(); test_intern_table();
lex_test(); lex_test();
String result = compile_file("globals.kl"_s); // String result = compile_file("globals.kl"_s);
// String result = compile_file("lambdas.kl"_s); String result = compile_file("structs.kl"_s);
// String result = compile_file("order_independent_globals.kl"_s); // String result = compile_file("order_independent_globals.kl"_s);
printf("%s", result.str); printf("%s", result.str);

View File

@@ -100,13 +100,14 @@ enum Ast_Kind{
AST_BLOCK, AST_BLOCK,
AST_LAMBDA, AST_LAMBDA,
AST_LAMBDA_ARG, AST_LAMBDA_ARG,
AST_STRUCT,
AST_CONST, AST_CONST,
AST_VAR, AST_VAR,
};
AST_TYPESPEC_IDENT, typedef U32 Ast_Flag;
AST_TYPESPEC_POINTER, enum{
AST_TYPESPEC_ARRAY, AST_EXPR = 1,
AST_TYPESPEC_LAMBDA
}; };
struct Ast{ struct Ast{
@@ -115,11 +116,12 @@ struct Ast{
Ast_Kind kind; Ast_Kind kind;
Ast *parent; Ast *parent;
Ast_Flag flags;
// @todo? // @todo?
// bool is_atom: 1; // bool is_atom: 1;
// bool is_stmt: 1; // bool is_stmt: 1;
// bool is_expr: 1;
// bool is_decl: 1; // bool is_decl: 1;
// bool is_expr: 1;
// bool is_named: 1; // bool is_named: 1;
}; };
@@ -211,6 +213,12 @@ struct Ast_Array: Ast_Expr{
Ast_Expr *expr; Ast_Expr *expr;
}; };
struct Ast_Struct: Ast{
// Required to be Ast_Struct or Ast_Var or Ast_Const
Array<Ast *> members;
};
struct Ast_Named:Ast{ struct Ast_Named:Ast{
Intern_String name; Intern_String name;
}; };
@@ -221,7 +229,7 @@ struct Ast_Var: Ast_Named{
}; };
struct Ast_Const: Ast_Named{ struct Ast_Const: Ast_Named{
Ast_Expr *expr; Ast *value;
}; };
struct Ast_Package:Ast{ struct Ast_Package:Ast{
@@ -240,22 +248,25 @@ 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_str(Token *pos, Intern_String string, Ast_Flag flags = 0){
AST_NEW(Atom, STR, pos); AST_NEW(Atom, STR, pos);
result->flags = flags;
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_ident(Token *pos, Intern_String string, Ast_Flag flags = 0){
AST_NEW(Atom, IDENT, pos); AST_NEW(Atom, IDENT, pos);
result->flags = flags;
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_int(Token *pos, S64 integer, Ast_Flag flags){
AST_NEW(Atom, INT, pos); AST_NEW(Atom, INT, pos);
result->flags = flags;
result->int_val = integer; result->int_val = integer;
return result; return result;
} }
@@ -263,6 +274,7 @@ ast_int(Token *pos, S64 integer){
function Ast_Expr * function Ast_Expr *
ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
AST_NEW(Binary, BINARY, op); AST_NEW(Binary, BINARY, op);
result->flags = AST_EXPR;
result->op = op->kind; result->op = op->kind;
result->left = left; result->left = left;
result->right = right; result->right = right;
@@ -274,6 +286,7 @@ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
function Ast_Compound * function Ast_Compound *
ast_expr_compound(Token *pos, Ast_Expr *typespec, Array<Ast_Compound_Item *> exprs){ ast_expr_compound(Token *pos, Ast_Expr *typespec, Array<Ast_Compound_Item *> exprs){
AST_NEW(Compound, COMPOUND, pos); AST_NEW(Compound, COMPOUND, pos);
result->flags = AST_EXPR;
result->typespec = typespec; result->typespec = typespec;
result->exprs = exprs.tight_copy(pctx->perm); result->exprs = exprs.tight_copy(pctx->perm);
if(result->typespec) result->typespec->parent = result; if(result->typespec) result->typespec->parent = result;
@@ -284,6 +297,7 @@ ast_expr_compound(Token *pos, Ast_Expr *typespec, Array<Ast_Compound_Item *> exp
function Ast_Compound_Item * function Ast_Compound_Item *
ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Atom *name, Ast_Expr *item){ ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Atom *name, Ast_Expr *item){
AST_NEW(Compound_Item, COMPOUND_ITEM, pos); AST_NEW(Compound_Item, COMPOUND_ITEM, pos);
result->flags = AST_EXPR;
result->name = name; result->name = name;
result->index = index; result->index = index;
result->item = item; result->item = item;
@@ -296,6 +310,7 @@ ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Atom *name, Ast_Expr *it
function Ast_Expr * function Ast_Expr *
ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Expr *typespec){ ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Expr *typespec){
AST_NEW(Cast, CAST, pos); AST_NEW(Cast, CAST, pos);
result->flags = AST_EXPR;
result->expr = expr; result->expr = expr;
result->typespec = typespec; result->typespec = typespec;
expr->parent = result; expr->parent = result;
@@ -306,6 +321,7 @@ ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Expr *typespec){
function Ast_Expr * function Ast_Expr *
ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){ ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){
AST_NEW(Unary, UNARY, pos); AST_NEW(Unary, UNARY, pos);
result->flags = AST_EXPR;
result->expr = expr; result->expr = expr;
result->op = op; result->op = op;
expr->parent = result; expr->parent = result;
@@ -315,6 +331,7 @@ ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){
function Ast_Expr * function Ast_Expr *
ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
AST_NEW(Index, INDEX, pos); AST_NEW(Index, INDEX, pos);
result->flags = AST_EXPR;
result->expr = expr; result->expr = expr;
result->index = index; result->index = index;
expr->parent = result; expr->parent = result;
@@ -325,6 +342,7 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
function Ast_Lambda * function Ast_Lambda *
ast_lambda(Token *pos, Array<Ast_Lambda_Arg *> params, Ast_Expr *ret, Ast_Block *block){ ast_lambda(Token *pos, Array<Ast_Lambda_Arg *> params, Ast_Expr *ret, Ast_Block *block){
AST_NEW(Lambda, LAMBDA, pos); AST_NEW(Lambda, LAMBDA, pos);
result->flags = AST_EXPR;
result->args = params.tight_copy(pctx->perm); result->args = params.tight_copy(pctx->perm);
result->block = block; result->block = block;
result->ret = ret; result->ret = ret;
@@ -339,6 +357,7 @@ ast_lambda(Token *pos, Array<Ast_Lambda_Arg *> params, Ast_Expr *ret, Ast_Block
function Ast_Lambda_Arg * function Ast_Lambda_Arg *
ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Expr *typespec){ ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Expr *typespec){
AST_NEW(Lambda_Arg, LAMBDA_ARG, pos); AST_NEW(Lambda_Arg, LAMBDA_ARG, pos);
result->flags = AST_EXPR;
result->name = name; result->name = name;
result->typespec = typespec; result->typespec = typespec;
result->typespec->parent = result; result->typespec->parent = result;
@@ -387,11 +406,23 @@ ast_init(Token *pos, Token_Kind op, Ast_Atom *ident, Ast_Expr *expr){
function Ast_Array * function Ast_Array *
ast_array(Token *pos, Ast_Expr *expr){ ast_array(Token *pos, Ast_Expr *expr){
AST_NEW(Array, ARRAY, pos); AST_NEW(Array, ARRAY, pos);
result->flags = AST_EXPR;
result->expr = expr; result->expr = expr;
result->expr->parent = result; result->expr->parent = result;
return result; return result;
} }
function Ast_Struct *
ast_struct(Token *pos, Array<Ast *> members){
AST_NEW(Struct, STRUCT, pos);
result->members = members.tight_copy(pctx->perm);
For(result->members) {
assert(it[0]->kind == AST_VAR || it[0]->kind == AST_CONST || it[0]->kind == AST_STRUCT);
it[0]->parent = result;
}
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Declarations // Declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -407,11 +438,13 @@ ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
} }
function Ast_Const * function Ast_Const *
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){ ast_const(Token *pos, Intern_String name, Ast *value){
AST_NEW(Const, CONST, pos); AST_NEW(Const, CONST, pos);
result->expr = expr;
assert(value->kind == AST_STRUCT || is_flag_set(value->flags, AST_EXPR));
result->value = value;
result->name = name; result->name = name;
result->expr->parent = result; result->value->parent = result;
return result; return result;
} }

View File

@@ -281,9 +281,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); case TK_StringLit : return ast_str(token, token->intern_val, AST_EXPR);
case TK_Identifier : return ast_ident(token, token->intern_val); case TK_Identifier : return ast_ident(token, token->intern_val, AST_EXPR);
case TK_Integer : return ast_int(token, token->int_val); case TK_Integer : return ast_int(token, token->int_val, AST_EXPR);
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());
case TK_OpenBracket: { case TK_OpenBracket: {
@@ -386,6 +386,23 @@ parse_assign_expr(){
return result; return result;
} }
function Ast_Struct *
parse_struct(Token *pos){
Scratch scratch;
Array<Ast *> members = {scratch};
token_match(OPEN_SCOPE);
do{
Token *token = token_get();
Ast_Named *named = parse_named(false);
if(!named) parsing_error(token, "Failed to parse struct member");
}while(token_match(SAME_SCOPE));
token_expect(CLOSE_SCOPE);
Ast_Struct *result = ast_struct(pos, members);
return result;
}
function Ast_Named * function Ast_Named *
parse_named(B32 is_global){ parse_named(B32 is_global){
Ast_Named *result = 0; Ast_Named *result = 0;
@@ -393,10 +410,24 @@ parse_named(B32 is_global){
if(token_is(TK_Identifier)){ if(token_is(TK_Identifier)){
if(is_global && pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented"); if(is_global && pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented");
Token *name = token_next(); Token *name = token_next();
if(token_match(TK_DoubleColon)){ // Constant
Ast_Expr *expr = parse_expr(); // @note: parse constant
result = ast_const(name, name->intern_val, expr); if(token_match(TK_DoubleColon)){
// parse struct binding
Token *struct_pos = token_get();
if(token_match_keyword(keyword_struct)){
Ast_Struct *struct_val = parse_struct(struct_pos);
result = ast_const(name, name->intern_val, struct_val);
}
// parse constant expression
else{
Ast_Expr *expr = parse_expr();
result = ast_const(name, name->intern_val, expr);
}
} }
// @note: parse variable
else if(token_match(TK_Colon)){ else if(token_match(TK_Colon)){
Ast_Expr *typespec = 0; Ast_Expr *typespec = 0;
Ast_Expr *expr = 0; Ast_Expr *expr = 0;

View File

@@ -504,7 +504,7 @@ eval_decl(Ast *ast, Sym *sym){
} }
Ast_Begin(AST_CONST, Ast_Const){ Ast_Begin(AST_CONST, Ast_Const){
Operand expr = eval_expr(node->expr, 0, sym); Operand expr = eval_expr((Ast_Expr *)node->value, 0, sym);
if(!expr.type) parsing_error(node->pos, "Constant value without expression"); if(!expr.type) parsing_error(node->pos, "Constant value without expression");
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");
return expr; return expr;
@@ -519,8 +519,8 @@ function Ast_Lambda *
ast_get_lambda(Ast *ast){ ast_get_lambda(Ast *ast){
if(ast->kind == AST_CONST){ if(ast->kind == AST_CONST){
auto ast_const = (Ast_Const *)ast; auto ast_const = (Ast_Const *)ast;
if(ast_const->expr){ if(ast_const->value){
auto ast_expr = ast_const->expr; auto ast_expr = ast_const->value;
if(ast_expr->kind == AST_LAMBDA){ if(ast_expr->kind == AST_LAMBDA){
return (Ast_Lambda *)ast_expr; return (Ast_Lambda *)ast_expr;
} }

View File

@@ -13,6 +13,8 @@ unifying the call expression and compound expression
seems more unified and better for coherence seems more unified and better for coherence
but more abigous and probably harder to implement but more abigous and probably harder to implement
value :: call((thing: int): int thing += 1; return thing, )
*/ */

0
structs.kl Normal file
View File