Added lambda expressions, lambda types, no body yet

This commit is contained in:
Krzosa Karol
2022-05-20 17:16:53 +02:00
parent 30736d37b6
commit 236ff0cd64
8 changed files with 329 additions and 153 deletions

View File

@@ -20,21 +20,14 @@ struct Parse_Ctx:Lexer{
Allocator *perm; // Stores: AST, tokens, interns Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap; Allocator *heap;
U64 unique_ids;
Map global_syms; Map global_syms;
Map type_map; Map type_map;
Token empty_token; Token empty_token;
S64 indent; S64 indent;
S64 pt[256]; // precedence table
void init(Allocator *perm_allocator, Allocator *heap_allocator){ void init(Allocator *perm_allocator, Allocator *heap_allocator){
const S64 addp = 1;
const S64 mulp = 2;
pt[TK_Add] = addp;
pt[TK_Sub] = addp;
pt[TK_Div] = mulp;
pt[TK_Mul] = mulp;
perm = perm_allocator; perm = perm_allocator;
heap = heap_allocator; heap = heap_allocator;
@@ -61,30 +54,33 @@ thread_local Parse_Ctx *pctx;
// AST // AST
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
enum Ast_Kind{ enum Ast_Kind{
AK_None, AST_NONE,
AK_Package, AST_PACKAGE,
AK_Expr_Str, AST_STR,
AK_Expr_Int, AST_INT,
AK_Expr_Cast, AST_CAST,
AK_Expr_Ident, AST_IDENT,
AK_Expr_Binary, AST_INDEX,
AK_Expr_CompoundItem, AST_UNARY,
AK_Expr_Compound, AST_BINARY,
AST_COMPOUND_ITEM,
AST_COMPOUND,
AK_Decl_Func, AST_LAMBDA,
AK_Decl_Func_Arg, AST_LAMBDA_PARAM,
AK_Decl_Const, AST_CONST,
AK_Decl_Var, AST_VAR,
AK_Typespec_Ident, AST_TYPESPEC_IDENT,
AK_Typespec_Pointer, AST_TYPESPEC_POINTER,
AK_Typespec_Array, AST_TYPESPEC_ARRAY,
AK_Typespec_Func AST_TYPESPEC_LAMBDA
}; };
struct Ast{ struct Ast{
U64 id;
Ast_Kind kind; Ast_Kind kind;
Token *pos; Token *pos;
}; };
@@ -94,6 +90,11 @@ struct Ast_Expr:Ast{
union{ union{
Intern_String intern_val; Intern_String intern_val;
U64 int_val; U64 int_val;
struct{
Token_Kind op;
Ast_Expr *expr;
}unary;
struct{ struct{
Token_Kind op; Token_Kind op;
Ast_Expr *left; Ast_Expr *left;
@@ -112,21 +113,31 @@ struct Ast_Expr:Ast{
Ast_Expr *expr; Ast_Expr *expr;
Ast_Typespec *typespec; Ast_Typespec *typespec;
}cast; }cast;
struct{
Ast_Expr *expr;
Ast_Expr *index;
}index;
struct{
Intern_String name;
Ast_Typespec *typespec;
}lambda_param;
}; };
}; };
struct Ast_Lambda : Ast_Expr {
Array<Ast_Expr *> params;
Ast_Typespec *ret;
};
struct Ast_Typespec:Ast{ struct Ast_Typespec:Ast{
union{ union{
Ast_Typespec *base; Ast_Typespec *base;
Intern_String name; Intern_String name;
struct{ struct{
Ast_Typespec *base; Ast_Typespec *base;
Ast_Expr *expr; Ast_Expr *expr;
}arr; }arr;
struct{ Ast_Lambda *lambda;
Ast_Typespec *ret;
Array<Ast_Typespec*> args;
}func;
}; };
}; };
@@ -153,34 +164,35 @@ struct Ast_Package:Ast{
// AST Constructors beginning with expressions // AST Constructors beginning with expressions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define AST_NEW(T,ikind,ipos) \ #define AST_NEW(T,ikind,ipos) \
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \ Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
result->kind = ikind; \ result->kind = ikind; \
result->pos = ipos result->pos = ipos; \
result->id = ++pctx->unique_ids
function Ast_Expr * function Ast_Expr *
ast_expr_string(Token *pos, Intern_String string){ ast_expr_string(Token *pos, Intern_String string){
AST_NEW(Expr, AK_Expr_Str, pos); AST_NEW(Expr, AST_STR, pos);
result->intern_val = string; result->intern_val = string;
return result; return result;
} }
function Ast_Expr * function Ast_Expr *
ast_expr_identifier(Token *pos, Intern_String string){ ast_expr_identifier(Token *pos, Intern_String string){
AST_NEW(Expr, AK_Expr_Ident, pos); AST_NEW(Expr, AST_IDENT, pos);
result->intern_val = string; result->intern_val = string;
return result; return result;
} }
function Ast_Expr * function Ast_Expr *
ast_expr_integer(Token *pos, S64 integer){ ast_expr_integer(Token *pos, S64 integer){
AST_NEW(Expr, AK_Expr_Int, pos); AST_NEW(Expr, AST_INT, pos);
result->int_val = integer; result->int_val = integer;
return result; return result;
} }
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(Expr, AK_Expr_Binary, op); AST_NEW(Expr, AST_BINARY, op);
result->binary.op = op->kind; result->binary.op = op->kind;
result->binary.left = left; result->binary.left = left;
result->binary.right = right; result->binary.right = right;
@@ -189,7 +201,7 @@ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
function Ast_Expr * function Ast_Expr *
ast_expr_compound(Token *pos, Ast_Typespec *typespec, Array<Ast_Expr *> exprs){ ast_expr_compound(Token *pos, Ast_Typespec *typespec, Array<Ast_Expr *> exprs){
AST_NEW(Expr, AK_Expr_Compound, pos); AST_NEW(Expr, AST_COMPOUND, pos);
result->compound.typespec = typespec; result->compound.typespec = typespec;
result->compound.exprs = exprs.tight_copy(pctx->perm); result->compound.exprs = exprs.tight_copy(pctx->perm);
return result; return result;
@@ -197,7 +209,7 @@ ast_expr_compound(Token *pos, Ast_Typespec *typespec, Array<Ast_Expr *> exprs){
function Ast_Expr * function Ast_Expr *
ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Expr *name, Ast_Expr *item){ ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Expr *name, Ast_Expr *item){
AST_NEW(Expr, AK_Expr_CompoundItem, pos); AST_NEW(Expr, AST_COMPOUND_ITEM, pos);
result->compound_item.name = name; result->compound_item.name = name;
result->compound_item.index = index; result->compound_item.index = index;
result->compound_item.item = item; result->compound_item.item = item;
@@ -206,42 +218,80 @@ ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Expr *name, Ast_Expr *it
function Ast_Expr * function Ast_Expr *
ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Typespec *typespec){ ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Typespec *typespec){
AST_NEW(Expr, AK_Expr_Cast, pos); AST_NEW(Expr, AST_CAST, pos);
result->cast.expr = expr; result->cast.expr = expr;
result->cast.typespec = typespec; result->cast.typespec = typespec;
return result; return result;
} }
function Ast_Expr *
ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){
AST_NEW(Expr, AST_UNARY, pos);
result->unary.expr = expr;
result->unary.op = op;
return result;
}
function Ast_Expr *
ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
AST_NEW(Expr, AST_INDEX, pos);
result->index.expr = expr;
result->index.index = index;
return result;
}
function Ast_Lambda *
ast_lambda(Token *pos, Array<Ast_Expr *> params, Ast_Typespec *ret){
AST_NEW(Lambda, AST_LAMBDA, pos);
result->params = params.tight_copy(pctx->perm);
result->ret = ret;
return result;
}
function Ast_Expr *
ast_expr_lambda_empty(Token *pos){
AST_NEW(Expr, AST_LAMBDA, pos);
return result;
}
function Ast_Expr *
ast_expr_lambda_param(Token *pos, Intern_String name, Ast_Typespec *typespec){
AST_NEW(Expr, AST_LAMBDA_PARAM, pos);
result->lambda_param.name = name;
result->lambda_param.typespec = typespec;
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Typespecs // Typespecs
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function Ast_Typespec * function Ast_Typespec *
ast_typespec_name(Token *pos, Intern_String name){ ast_typespec_name(Token *pos, Intern_String name){
AST_NEW(Typespec, AK_Typespec_Ident, pos); AST_NEW(Typespec, AST_TYPESPEC_IDENT, pos);
result->name = name; result->name = name;
return result; return result;
} }
function Ast_Typespec * function Ast_Typespec *
ast_typespec_pointer(Token *pos, Ast_Typespec *base){ ast_typespec_pointer(Token *pos, Ast_Typespec *base){
AST_NEW(Typespec, AK_Typespec_Pointer, pos); AST_NEW(Typespec, AST_TYPESPEC_POINTER, pos);
result->base = base; result->base = base;
return result; return result;
} }
function Ast_Typespec * function Ast_Typespec *
ast_typespec_array(Token *pos, Ast_Typespec *base, Ast_Expr *expr){ ast_typespec_array(Token *pos, Ast_Typespec *base, Ast_Expr *expr){
AST_NEW(Typespec, AK_Typespec_Array, pos); AST_NEW(Typespec, AST_TYPESPEC_ARRAY, pos);
result->arr.base = base; result->arr.base = base;
result->arr.expr = expr; result->arr.expr = expr;
return result; return result;
} }
function Ast_Typespec * function Ast_Typespec *
ast_typespec_func(Token *pos, Ast_Typespec *ret, Array<Ast_Typespec*> args){ ast_typespec_lambda(Token *pos, Ast_Lambda *lambda){
AST_NEW(Typespec, AK_Typespec_Func, pos); AST_NEW(Typespec, AST_TYPESPEC_LAMBDA, pos);
result->func.ret = ret; result->lambda = lambda;
result->func.args = args.tight_copy(pctx->perm);
return result; return result;
} }
@@ -250,14 +300,14 @@ ast_typespec_func(Token *pos, Ast_Typespec *ret, Array<Ast_Typespec*> args){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function Ast_Decl * function Ast_Decl *
ast_decl_func(Token *pos, Intern_String name){ ast_decl_func(Token *pos, Intern_String name){
AST_NEW(Decl, AK_Decl_Func, pos); AST_NEW(Decl, AST_LAMBDA, pos);
result->name = name; result->name = name;
return result; return result;
} }
function Ast_Decl * function Ast_Decl *
ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *expr){ ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *expr){
AST_NEW(Decl, AK_Decl_Var, pos); AST_NEW(Decl, AST_VAR, pos);
result->var.expr = expr; result->var.expr = expr;
result->var.typespec = typespec; result->var.typespec = typespec;
result->name = name; result->name = name;
@@ -267,13 +317,13 @@ ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *e
function Ast_Decl * function Ast_Decl *
ast_decl_const(Token *pos, Intern_String name, Ast_Expr *expr){ ast_decl_const(Token *pos, Intern_String name, Ast_Expr *expr){
Ast_Decl *result = ast_decl_var(pos, 0, name, expr); Ast_Decl *result = ast_decl_var(pos, 0, name, expr);
result->kind = AK_Decl_Const; result->kind = AST_CONST;
return result; return result;
} }
function Ast_Package * function Ast_Package *
ast_package(Token *pos, String name, Array<Ast_Decl *> decls){ ast_package(Token *pos, String name, Array<Ast_Decl *> decls){
AST_NEW(Package, AK_Package, pos); AST_NEW(Package, AST_PACKAGE, pos);
result->decls = decls.tight_copy(pctx->perm); result->decls = decls.tight_copy(pctx->perm);
result->name = intern_string(&pctx->interns, name); result->name = intern_string(&pctx->interns, name);
return result; return result;

View File

@@ -82,6 +82,9 @@ enum Token_Kind{
TK_Float, TK_Float,
TK_Integer, TK_Integer,
TK_Keyword, TK_Keyword,
TK_Pointer = TK_BitXor,
TK_Dereference,
}; };
struct Token{ struct Token{

View File

@@ -21,8 +21,8 @@ token_next(){
} }
function Token * function Token *
token_is(Token_Kind kind){ token_is(Token_Kind kind, S64 lookahead = 0){
Token *token = token_get(); Token *token = token_get(lookahead);
if(token->kind == kind){ if(token->kind == kind){
return token; return token;
} }
@@ -158,12 +158,45 @@ parse_expr_compound(){
return result; return result;
} }
function Ast_Typespec *
parse_optional_type(){
Ast_Typespec *result = 0;
if(token_match(TK_Colon)) result = parse_typespec();
return result;
}
function Ast_Lambda *
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
// @Todo(Krzosa): Combine this with typespec function parsing
Scratch scratch;
Array<Ast_Expr *> params = {scratch};
// @Note(Krzosa): No need to guard against "()"
// We needed to lookahead to verify it's a function
// and this routine only fires when we have situation
// with at least one parameter
for(;;){
Token *name = token_expect(TK_Identifier);
token_expect(TK_Colon);
Ast_Typespec *typespec = parse_typespec();
Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec);
params.add(param);
if(!token_match(TK_Comma)){
break;
}
}
token_expect(TK_CloseParen);
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
return result;
}
function Ast_Expr * function Ast_Expr *
parse_expr_nud(Token *token){ null_denotation(Token *token){
switch(token->kind){ switch(token->kind){
case TK_StringLit: return ast_expr_string(token, token->intern_val); case TK_StringLit : return ast_expr_string(token, token->intern_val);
case TK_Identifier: return ast_expr_identifier(token, token->intern_val); case TK_Identifier: return ast_expr_identifier(token, token->intern_val);
case TK_Integer: return ast_expr_integer(token, token->int_val); case TK_Integer : return ast_expr_integer(token, token->int_val);
case TK_BitXor : return ast_expr_unary(token, TK_Dereference, parse_expr());
case TK_Keyword: { case TK_Keyword: {
if(token->intern_val == keyword_cast){ if(token->intern_val == keyword_cast){
token_expect(TK_OpenParen); token_expect(TK_OpenParen);
@@ -179,22 +212,41 @@ parse_expr_nud(Token *token){
} }
}break; }break;
case TK_OpenBrace: return parse_expr_compound(); case TK_OpenBrace: return parse_expr_compound();
case TK_OpenParen: {Ast_Expr *result = parse_expr(); token_expect(TK_CloseParen); return result;} case TK_OpenParen: {
if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token);
else if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token);
else{
Ast_Expr *result = parse_expr();
token_expect(TK_CloseParen);
return result;
}
}
default: parsing_error(token, "Unexpected token of kind: [%s] in expression", token_kind_string(token->kind).str); return 0; default: parsing_error(token, "Unexpected token of kind: [%s] in expression", token_kind_string(token->kind).str); return 0;
} }
} }
function S64 function S64
op_precedence(Token_Kind kind){ left_binding_power(Token_Kind kind){
S64 result = pctx->pt[kind]; switch(kind){
return result; case TK_Sub: case TK_Add: return 1;
case TK_Mul: case TK_Div: return 2;
default: return 0;
}
}
function S64
postfix_binding_power(Token_Kind kind){
switch(kind){
case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1;
default: return 0;
}
} }
function Ast_Expr * function Ast_Expr *
parse_expr_led(Token *op, Ast_Expr *left){ left_denotation(Token *op, Ast_Expr *left){
enum{ Left_Associative, Right_Associative }; enum{ Left_Associative, Right_Associative };
S64 assoc = Left_Associative; S64 assoc = Left_Associative;
Ast_Expr *right = parse_expr(op_precedence(op->kind) - assoc); Ast_Expr *right = parse_expr(left_binding_power(op->kind) - assoc);
switch(op->kind){ switch(op->kind){
case TK_Add: case TK_Mul: case TK_Sub: case TK_Div: return ast_expr_binary(left, right, op); case TK_Add: case TK_Mul: case TK_Sub: case TK_Div: return ast_expr_binary(left, right, op);
default: parsing_error(op, "Unexpected token of kind: [%s] in expression", token_kind_string(op->kind).str); return 0; default: parsing_error(op, "Unexpected token of kind: [%s] in expression", token_kind_string(op->kind).str); return 0;
@@ -204,10 +256,30 @@ parse_expr_led(Token *op, Ast_Expr *left){
function Ast_Expr * function Ast_Expr *
parse_expr(S64 rbp){ parse_expr(S64 rbp){
Token *token = token_next(); Token *token = token_next();
Ast_Expr *left = parse_expr_nud(token); Ast_Expr *left = null_denotation(token);
while(rbp < op_precedence(token_get()->kind)){ for(;;){
token = token_next(); token = token_get();
left = parse_expr_led(token, left);
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_BitXor || token->kind == TK_OpenBracket)){
token_next();
if(token->kind == TK_OpenBracket){
Ast_Expr *index = parse_expr();
left = ast_expr_index(token, left, index);
token_expect(TK_CloseBracket);
}
else{
if(token->kind == TK_Increment) token->kind = TK_PostIncrement;
else if(token->kind == TK_Decrement) token->kind = TK_PostDecrement;
left = ast_expr_unary(token, token->kind, left);
}
}
else if(rbp < left_binding_power(token->kind)){
token = token_next();
left = left_denotation(token, left);
}
else break;
} }
return left; return left;
} }
@@ -215,8 +287,16 @@ parse_expr(S64 rbp){
function S64 function S64
expr_eval(Ast_Expr *expr){ expr_eval(Ast_Expr *expr){
switch(expr->kind){ switch(expr->kind){
case AK_Expr_Int: return expr->int_val; case AST_INT: return expr->int_val;
case AK_Expr_Binary : { case AST_UNARY:{
S64 value = expr_eval(expr->unary.expr);
switch(expr->unary.op){
case TK_PostDecrement: return value - 1;
case TK_PostIncrement: return value + 1;
default: invalid_codepath;
}
}break;
case AST_BINARY : {
S64 left = expr_eval(expr->binary.left); S64 left = expr_eval(expr->binary.left);
S64 right = expr_eval(expr->binary.right); S64 right = expr_eval(expr->binary.right);
switch(expr->binary.op){ switch(expr->binary.op){
@@ -243,6 +323,8 @@ test_parse_expr(){
TEST_PARSER(); TEST_PARSER();
struct Test{String str;S64 val;}; struct Test{String str;S64 val;};
Array<Test> exprs = {scratch}; Array<Test> exprs = {scratch};
//exprs.add({"thing[1][2][3]"_s, 0});
exprs.add({"4++++--"_s, 5});
exprs.add({"(4+5)*2"_s, (4+5)*2}); exprs.add({"(4+5)*2"_s, (4+5)*2});
exprs.add({"4+5*2"_s, 4+5*2}); exprs.add({"4+5*2"_s, 4+5*2});
exprs.add({"4*5+5"_s, 4*5+5}); exprs.add({"4*5+5"_s, 4*5+5});
@@ -259,36 +341,12 @@ test_parse_expr(){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Parsing declarations // Parsing declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function Ast_Typespec *
parse_optional_type(){
Ast_Typespec *result = 0;
if(token_match(TK_Colon)) result = parse_typespec();
return result;
}
function Ast_Typespec *
parse_typespec_function(Token *token){
Scratch scratch;
Array<Ast_Typespec *> args = {scratch};
if(!token_is(TK_CloseParen)) {
for(;;) {
args.add(parse_typespec());
if(!token_match(TK_Comma)){
break;
}
}
}
token_expect(TK_CloseParen);
Ast_Typespec *ret = parse_optional_type();
Ast_Typespec *result = ast_typespec_func(token, ret, args);
return result;
}
// [10]*int - Array of 10 pointers to ints // [10]*int - Array of 10 pointers to ints
function Ast_Typespec * function Ast_Typespec *
parse_typespec_recurse(){ parse_typespec_recurse(){
Token *token = token_get(); Token *token = token_get();
if(token_match(TK_Mul)){ if(token_match(TK_BitXor)){
Ast_Typespec *result = parse_typespec_recurse(); Ast_Typespec *result = parse_typespec_recurse();
result = ast_typespec_pointer(token, result); result = ast_typespec_pointer(token, result);
return result; return result;
@@ -301,8 +359,8 @@ parse_typespec_recurse(){
return result; return result;
} }
else if(token_match(TK_OpenParen)){ else if(token_match(TK_OpenParen)){
Ast_Typespec *result = parse_typespec_function(token); Ast_Lambda *result = parse_lambda(token, true);
return result; return ast_typespec_lambda(token, result);
} }
else if(token_match(TK_Identifier)){ else if(token_match(TK_Identifier)){
Ast_Typespec *result = ast_typespec_name(token, token->intern_val); Ast_Typespec *result = ast_typespec_name(token, token->intern_val);

View File

@@ -1,4 +1,4 @@
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast; #define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
#define Ast_End() } break #define Ast_End() } break
enum Sym_Kind{ enum Sym_Kind{
@@ -97,7 +97,7 @@ eval_typespec(Ast_Typespec *ast){
if(!ast) return 0; if(!ast) return 0;
switch(ast->kind){ switch(ast->kind){
Ast_Begin(AK_Typespec_Ident, Ast_Typespec){ Ast_Begin(AST_TYPESPEC_IDENT, Ast_Typespec){
Sym *type_sym = sym_get(node->name); Sym *type_sym = sym_get(node->name);
if(!type_sym){ if(!type_sym){
parsing_error(node->pos, "This type is not defined"); parsing_error(node->pos, "This type is not defined");
@@ -109,14 +109,24 @@ eval_typespec(Ast_Typespec *ast){
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Typespec_Pointer, Ast_Typespec){ Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
Scratch scratch;
Type *ret = eval_typespec(node->lambda->ret);
Array<Type *> params = {scratch};
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
Type *result = type_lambda(ret, params);
return result;
Ast_End();
}
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
Type *type = eval_typespec(node->base); Type *type = eval_typespec(node->base);
Type *result = type_pointer(type); Type *result = type_pointer(type);
return result; return result;
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Typespec_Array, Ast_Typespec){ Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
Type *type = eval_typespec(node->arr.base); Type *type = eval_typespec(node->arr.base);
Operand expr = eval_expr(node->arr.expr); Operand expr = eval_expr(node->arr.expr);
if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant"); if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant");
@@ -149,19 +159,35 @@ resolve_type_pair(Token *pos, Type *a, Type *b){
function Operand function Operand
eval_expr(Ast_Expr *ast, Type *exp_compound_type){ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
switch(ast->kind){ switch(ast->kind){
Ast_Begin(AK_Expr_Int, Ast_Expr){ Ast_Begin(AST_INT, Ast_Expr){
Operand result = {type_int, true, {.int_val=(S64)node->int_val}}; Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
return result; return result;
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Expr_Str, Ast_Expr){ Ast_Begin(AST_STR, Ast_Expr){
Operand result = {type_string, true, {.intern_val = node->intern_val}}; Operand result = {type_string, true, {.intern_val = node->intern_val}};
return result; return result;
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Expr_Compound, Ast_Expr){ Ast_Begin(AST_LAMBDA, Ast_Lambda){
Type *type = eval_typespec(ast_typespec_lambda(0, node));
return {type, true};
Ast_End();
}
Ast_Begin(AST_INDEX, Ast_Expr){
Operand left = eval_expr(node->index.expr);
Operand index = eval_expr(node->index.index);
if(left.type->kind != TYPE_Array) parsing_error(node->pos, "Indexing variable that is not an array");
if(index.type != type_int) parsing_error(node->pos, "Trying to index the array with invalid type, expected int");
Operand result = {left.type->arr.base};
return result;
Ast_End();
}
Ast_Begin(AST_COMPOUND, Ast_Expr){
Type *type = eval_typespec(node->compound.typespec); Type *type = eval_typespec(node->compound.typespec);
Type *variable_type = exp_compound_type; Type *variable_type = exp_compound_type;
if(!type && variable_type) type = variable_type; if(!type && variable_type) type = variable_type;
@@ -173,16 +199,18 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Type *item_type = type->arr.base; Type *item_type = type->arr.base;
For(node->compound.exprs){ For(node->compound.exprs){
assert(it[0]->kind == AK_Expr_CompoundItem); assert(it[0]->kind == AST_COMPOUND_ITEM);
if(it[0]->compound_item.name) parsing_error(it[0]->pos, "Invalid array indexing in compound expression"); Ast_Expr *i = (Ast_Expr *)it[0];
if(it[0]->compound_item.index){ assert(i->kind == AST_COMPOUND_ITEM);
Operand index_op = eval_expr(it[0]->compound_item.index); if(i->compound_item.name) parsing_error(i->pos, "Invalid array indexing in compound expression");
if(!index_op.is_const) parsing_error(it[0]->pos, "Index in a compound expression is not a constant"); if(i->compound_item.index){
if(index_op.type != type_int) parsing_error(it[0]->pos, "Index should be of type int"); Operand index_op = eval_expr(i->compound_item.index);
if(index_op.int_val > (type->arr.size - 1)) parsing_error(it[0]->pos, "Invalid index in compound expression, larger then type can store"); if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
} }
Operand expr = eval_expr(it[0]->compound_item.item); Operand expr = eval_expr(i->compound_item.item);
if(expr.type != item_type) parsing_error(it[0]->pos, "Invalid type of item in compound expression"); resolve_type_pair(i->pos, expr.type, item_type);
} }
} }
else parsing_error(node->pos, "Invalid compound expression type"); else parsing_error(node->pos, "Invalid compound expression type");
@@ -192,7 +220,7 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Expr_Ident, Ast_Expr){ Ast_Begin(AST_IDENT, Ast_Expr){
Sym *sym = sym_get(node->intern_val); Sym *sym = sym_get(node->intern_val);
if(!sym){ if(!sym){
parsing_error(node->pos, "Identifier is undefined"); parsing_error(node->pos, "Identifier is undefined");
@@ -203,7 +231,7 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Expr_Cast, Ast_Expr){ Ast_Begin(AST_CAST, Ast_Expr){
Operand expr = eval_expr(node->cast.expr); Operand expr = eval_expr(node->cast.expr);
Type *type = eval_typespec(node->cast.typespec); Type *type = eval_typespec(node->cast.typespec);
@@ -229,7 +257,25 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Expr_Binary, Ast_Expr){ Ast_Begin(AST_UNARY, Ast_Expr){
Operand value = eval_expr(node->unary.expr);
switch(node->unary.op){
case TK_BitXor:{
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
Operand result = {value.type->base};
return result;
}break;
case TK_Dereference:{
Operand result = {type_pointer(value.type)};
return result;
}break;
invalid_default_case; return {};
}
Ast_End();
}
Ast_Begin(AST_BINARY, Ast_Expr){
Operand left = eval_expr(ast->binary.left); Operand left = eval_expr(ast->binary.left);
Operand right = eval_expr(ast->binary.right); Operand right = eval_expr(ast->binary.right);
Operand result = {}; Operand result = {};
@@ -262,14 +308,14 @@ function void
eval_decl(Ast *ast){ eval_decl(Ast *ast){
switch(ast->kind){ switch(ast->kind){
Ast_Begin(AK_Package, Ast_Package){ Ast_Begin(AST_PACKAGE, Ast_Package){
For(node->decls) eval_decl(*it); For(node->decls) eval_decl(*it);
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Decl_Var, Ast_Decl){ Ast_Begin(AST_VAR, Ast_Decl){
Type *type = eval_typespec(node->var.typespec); Type *type = eval_typespec(node->var.typespec);
Operand expr = eval_expr(node->var.expr, type); Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node); Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
@@ -277,7 +323,7 @@ eval_decl(Ast *ast){
Ast_End(); Ast_End();
} }
Ast_Begin(AK_Decl_Const, Ast_Decl){ Ast_Begin(AST_CONST, Ast_Decl){
Type *type = eval_typespec(node->var.typespec); Type *type = eval_typespec(node->var.typespec);
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer"); if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
Operand expr = eval_expr(node->var.expr); Operand expr = eval_expr(node->var.expr);

View File

@@ -111,7 +111,7 @@ type_array(Type *base, SizeU size){
} }
function Type * function Type *
type_function(Type *ret, Array<Type *> args){ type_lambda(Type *ret, Array<Type *> args){
U64 hash = hash_ptr(ret); U64 hash = hash_ptr(ret);
For(args) hash = hash_mix(hash, hash_ptr(*it)); For(args) hash = hash_mix(hash, hash_ptr(*it));
Type *result = (Type *)map_get_u64(&pctx->type_map, hash); Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
@@ -153,8 +153,8 @@ test_types(){
Array<Type*> types = {scratch}; Array<Type*> types = {scratch};
types.add(type_array(type_int, 32)); types.add(type_array(type_int, 32));
Type *func_type1 = type_function(types[0], types); Type *func_type1 = type_lambda(types[0], types);
Type *func_type2 = type_function(types[0], types); Type *func_type2 = type_lambda(types[0], types);
assert(func_type1 == func_type2); assert(func_type1 == func_type2);
Array<Type*> types2 = {scratch}; Array<Type*> types2 = {scratch};
@@ -163,8 +163,8 @@ test_types(){
types2.add(type_int); types2.add(type_int);
} }
types.add(type_int); types.add(type_int);
Type *func_type3 = type_function(types[0], types); Type *func_type3 = type_lambda(types[0], types);
Type *func_type4 = type_function(types[0], types2); Type *func_type4 = type_lambda(types[0], types2);
assert(func_type1 != func_type3); assert(func_type1 != func_type3);
assert(func_type3 == func_type4); assert(func_type3 == func_type4);
} }

View File

@@ -4,9 +4,6 @@ function void typespec_print(Typespec *spec);
global S64 indent; global S64 indent;
#define println(...) do{ printf("\n"); print_indent(); printf(__VA_ARGS__); }while(0) #define println(...) do{ printf("\n"); print_indent(); printf(__VA_ARGS__); }while(0)
#define AST_CAST(item, T) T *item = (T *)item
#define AST_IterT(parent, name, T) for(T *name = (T *)(parent)->first; name; name=(T *)name->next) // , assert(name->kind == AST_##type
#define AST_Iter(parent,name) AST_IterT(parent,name,AST)
function void function void

View File

@@ -1,35 +1,57 @@
/*
Player :: struct
id : int
name: String
compound_of_struct: Player = {
id = 10,
name = "Guy",
}
second_compound_syntax := :Player{...}
max :: (a: int, b: int) { if a > b then return a; return b; }
max :: (a: int, b: int)
if a > b then return a
return b
; - treated as new line
{ and } - treated as new line scope and end of new line scope
*/
test_function :: (thing: int): ^int
//-----------------------------------------------------------------------------
// Booleans
//-----------------------------------------------------------------------------
boolean: bool = true boolean: bool = true
value_of_bool: int = cast(boolean: int) value_of_bool: int = cast(boolean: int)
base := null base := null
//-----------------------------------------------------------------------------
// Compound expressions
//-----------------------------------------------------------------------------
array1: [4]int = {1,2,3,4} array1: [4]int = {1,2,3,4}
array2: [32]int = {1,2,3,4} array2: [32]int = {1,2,3,4}
array3: [32]int = { array3: [32]int = {
[0] = 0, [0] = 0,
[1] = 1,
[31] = 31, [31] = 31,
} }
array_item := array1[0]
array_item_imp: int = array2[2]
/* //-----------------------------------------------------------------------------
// Pointers
//-----------------------------------------------------------------------------
pointer_decl : ^int
variable_from_deref: int = pointer_decl^
pointer_from_var : ^int = ^variable_from_deref
boolean_pointer := ^boolean
pointer: *int
variable: int = *pointer
pointer_from_var := ^variable
pointer := &base
base_from_pointer := *pointer
structure: Data = {}
array2: [4]int = {
[0] = 0,
[1] = 1
}
array_to_pointer: *[4]int = &array1
array_to_pointer_imp : = &array1
*/
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Implicit type // Implicit type
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -39,9 +61,9 @@ implicit_str :: "Hello world"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Pointers // Pointers
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
pointer: *int = cast(null: *int) pointer: ^int = cast(null: ^int)
pointer2: *int = null pointer2: ^int = null
pointer3: **int = null pointer3: ^^int = null
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// String types // String types

10
type.c
View File

@@ -99,7 +99,7 @@ type_array(Arena *arena, Type *base, SizeU size){
} }
function Type * function Type *
type_function(Arena *arena, Type *ret, Type **params, S32 count){ type_lambda(Arena *arena, Type *ret, Type **params, S32 count){
U64 hash = hash_ptr(ret); U64 hash = hash_ptr(ret);
for(S32 i = 0; i < count; i++) for(S32 i = 0; i < count; i++)
hash = hash_mix(hash, hash_ptr(params[i])); hash = hash_mix(hash, hash_ptr(params[i]));
@@ -138,8 +138,8 @@ test_types(){
Type **types = 0; Type **types = 0;
array_push(types, type_array(arena, type_int, 32)); array_push(types, type_array(arena, type_int, 32));
Type *func_type1 = type_function(arena, types[0], types, array_len(types)); Type *func_type1 = type_lambda(arena, types[0], types, array_len(types));
Type *func_type2 = type_function(arena, types[0], types, array_len(types)); Type *func_type2 = type_lambda(arena, types[0], types, array_len(types));
assert(func_type1 == func_type2); assert(func_type1 == func_type2);
Type **types2 = 0; Type **types2 = 0;
@@ -148,8 +148,8 @@ test_types(){
array_push(types2, type_int); array_push(types2, type_int);
} }
array_push(types, type_int); array_push(types, type_int);
Type *func_type3 = type_function(arena, types[0], types, array_len(types)); Type *func_type3 = type_lambda(arena, types[0], types, array_len(types));
Type *func_type4 = type_function(arena, types[0], types2, array_len(types)); Type *func_type4 = type_lambda(arena, types[0], types2, array_len(types));
assert(func_type1 != func_type3); assert(func_type1 != func_type3);
assert(func_type3 == func_type4); assert(func_type3 == func_type4);