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

View File

@@ -7,8 +7,32 @@
#include "new_resolve.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
/// [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(){
@@ -23,8 +47,8 @@ int main(){
test_intern_table();
lex_test();
String result = compile_file("globals.kl"_s);
// String result = compile_file("lambdas.kl"_s);
// String result = compile_file("globals.kl"_s);
String result = compile_file("structs.kl"_s);
// String result = compile_file("order_independent_globals.kl"_s);
printf("%s", result.str);

View File

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

View File

@@ -281,9 +281,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);
case TK_Identifier : return ast_ident(token, token->intern_val);
case TK_Integer : return ast_int(token, token->int_val);
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_Pointer : return ast_expr_unary(token, TK_Pointer, parse_expr());
case TK_Dereference: return ast_expr_unary(token, TK_Dereference, parse_expr());
case TK_OpenBracket: {
@@ -386,6 +386,23 @@ parse_assign_expr(){
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 *
parse_named(B32 is_global){
Ast_Named *result = 0;
@@ -393,10 +410,24 @@ parse_named(B32 is_global){
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(token_match(TK_DoubleColon)){ // Constant
Ast_Expr *expr = parse_expr();
result = ast_const(name, name->intern_val, expr);
// @note: parse constant
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)){
Ast_Expr *typespec = 0;
Ast_Expr *expr = 0;

View File

@@ -504,7 +504,7 @@ eval_decl(Ast *ast, Sym *sym){
}
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.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
return expr;
@@ -519,8 +519,8 @@ function Ast_Lambda *
ast_get_lambda(Ast *ast){
if(ast->kind == AST_CONST){
auto ast_const = (Ast_Const *)ast;
if(ast_const->expr){
auto ast_expr = ast_const->expr;
if(ast_const->value){
auto ast_expr = ast_const->value;
if(ast_expr->kind == AST_LAMBDA){
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
but more abigous and probably harder to implement
value :: call((thing: int): int thing += 1; return thing, )
*/

0
structs.kl Normal file
View File