Generating valid c code, more work on null values

This commit is contained in:
Krzosa Karol
2022-05-24 20:33:11 +02:00
parent 236ff0cd64
commit 5176b40204
17 changed files with 698 additions and 1258 deletions

View File

@@ -1,3 +1,5 @@
@echo off @echo off
clang main.cpp -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib pushd %~dp0
clang main.cpp -O0 -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib
popd

232
cgenerate.cpp Normal file
View File

@@ -0,0 +1,232 @@
#define genln(...) do{printf("\n"); gen_indent(); gen(__VA_ARGS__); }while(0)
#define gen(...) printf(__VA_ARGS__)
global S32 global_indent;
function void
gen_indent(){
for(S32 i = 0; i < global_indent; i++) gen(" ");
}
// @todo: Gen complicated decl
//array 10 ( pointer (pointer array 5 int a))
// int (*(*(a[5])))[10]
//
// 1 Get to the bottom
// 2 Add variable name
// 3 Going backwards add arrays and pointers in parens
// 4 Add type name on the left side
function void
gen_simple_decl_prefix(Ast_Resolved_Type *ast){
switch(ast->kind){
case TYPE_Int: gen("int "); break;
case TYPE_Bool: gen("bool "); break;
case TYPE_Unsigned: gen("unsigned "); break;
case TYPE_String: gen("String "); break;
case TYPE_Void: gen("void "); break;
case TYPE_Pointer:{gen_simple_decl_prefix(ast->base); gen("*");} break;
case TYPE_Array: gen_simple_decl_prefix(ast->base); break;
case TYPE_Lambda:break;
invalid_default_case;
}
}
function void
gen_simple_decl_postfix(Ast_Resolved_Type *ast){
switch(ast->kind){
case TYPE_Int: break;
case TYPE_Bool: break;
case TYPE_Unsigned: break;
case TYPE_String: break;
case TYPE_Void: break;
case TYPE_Pointer: gen_simple_decl_postfix(ast->base); break;
case TYPE_Array: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
case TYPE_Lambda:break;
invalid_default_case;
}
}
function void
gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
if(ast->kind == TYPE_Lambda) {
gen_simple_decl_prefix(ast->func.ret);
gen("(*%s)(", name.str);
For(ast->func.args){
gen_simple_decl_prefix(it[0]);
if(it != ast->func.args.end() - 1) gen(", ");
}
gen(")");
}
else{
gen_simple_decl_prefix(ast);
if(name.len) {
gen("%s", name.str);
gen_simple_decl_postfix(ast);
}
}
}
function void
gen_expr(Ast_Expr *ast){
switch(ast->kind){
Ast_Begin(AST_IDENT, Ast_Expr){
gen("%s", node->intern_val.str);
Ast_End();
}
Ast_Begin(AST_INT, Ast_Expr){
gen("%lld", node->int_val);
Ast_End();
}
Ast_Begin(AST_STR, Ast_Expr){
gen("LIT(\"%s\")", node->intern_val.str);
Ast_End();
}
Ast_Begin(AST_INDEX, Ast_Expr){
gen_expr(node->index.expr);
gen("[");
gen_expr(node->index.index);
gen("]");
Ast_End();
}
Ast_Begin(AST_UNARY, Ast_Expr){
switch(node->unary.op){
case TK_Pointer: {
gen("(*");
gen_expr(node->unary.expr);
gen(")");
} break;
case TK_Dereference: {
gen("(&");
gen_expr(node->unary.expr);
gen(")");
} break;
invalid_default_case;
}
Ast_End();
}
Ast_Begin(AST_CAST, Ast_Expr){
gen("(");
gen("(");
gen_simple_decl(node->cast.typespec->resolved_type, {});
gen(")");
gen_expr(node->cast.expr);
gen(")");
Ast_End();
}
Ast_Begin(AST_COMPOUND, Ast_Expr){
gen("(");
gen_simple_decl(node->compound.type, {});
gen(")");
gen("{");
For(node->compound.exprs){
auto comp = it[0]->compound_item;
if(comp.name){
gen("[");
gen_expr(comp.name);
gen("] = ");
}
if(comp.index){
gen("[");
gen_expr(comp.index);
gen("] = ");
}
assert(comp.item);
gen_expr(comp.item);
if(!node->compound.exprs.is_last(it)) gen(", ");
}
gen("}");
Ast_End();
}
invalid_default_case;
}
}
function void
gen_ast(Ast *ast){
switch(ast->kind){
Ast_Begin(AST_PACKAGE, Ast_Package){
For(node->decls) gen_ast(*it);
Ast_End();
}
Ast_Begin(AST_VAR, Ast_Decl){
genln("");
Sym *sym = sym_get(node->name);
gen_simple_decl(sym->type, node->name);
if(node->var.expr){
gen(" = ");
gen_expr(node->var.expr);
}
gen(";");
Ast_End();
}
Ast_Begin(AST_CONST, Ast_Decl){
Sym *sym = sym_get(node->name);
if(sym->type->kind == TYPE_Lambda){
if(node->var.expr->kind == AST_LAMBDA){
Ast_Lambda *lambda = (Ast_Lambda *)node->var.expr;
genln("");
gen_simple_decl(lambda->ret->resolved_type, node->name);
gen("(");
For(lambda->params){
assert(it[0]->kind == AST_LAMBDA_PARAM);
gen_simple_decl(it[0]->lambda_param.typespec->resolved_type, it[0]->lambda_param.name);
if(it != (lambda->params.end() - 1)) gen(", ");
}
gen(")");
}
else{
genln("");
gen_simple_decl(sym->type, node->name);
gen(" = ");
gen_expr(node->var.expr);
gen(";");
}
}
else if(sym->type == type_int){
genln("enum { %s = %lld };", node->name.str, sym->int_val);
}
else if(sym->type == type_string){
genln("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
}
else{
parsing_error(node->pos, "Unhandled type of constant expression");
}
Ast_End();
}
invalid_default_case;
}
}
function void
test_gen(){
TEST_PARSER();
String filename = "test3.kl"_s;
String file_content = os_read_file(scratch, filename);
lex_restream(&ctx, file_content, filename);
Ast_Package *result = parse_file();
sym_insert_builtins();
eval_decl(result);
gen(R"==(
#define null_pointer 0
#define null_lambda 0
)==");
gen_ast(result);
__debugbreak();
}

View File

@@ -1,66 +0,0 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include "lang.h"
#include "os.h"
#include "memory.h"
#include "common.c"
#include "memory.c"
#include "scratch.c"
#include "os_win32.c"
#include "new_lex.c"
//-----------------------------------------------------------------------------
// String replacing util
//-----------------------------------------------------------------------------
typedef struct String_Map String_Map;
struct String_Map{
String replace;
String with;
};
function void
output_template(FILE *f, String filename, String_Map *map, SizeU map_cap){
Arena *scratch = arena_begin_scratch();
String file = os_read_file(scratch, filename);
Token_Array array = lex_stream(scratch, file, filename);
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
String string = t->string;
for(SizeU i = 0; i < map_cap; i++){
if(string_compare(string, map[i].replace)){
string = map[i].with;
break;
}
}
fprintf(f, "%.*s", (int)string.len, string.str);
if(t->kind == TK_OpenBrace) fprintf(f, "\n");
if(t->kind == TK_CloseBrace && token_array_iter_peek(&array, 0)->kind != TK_Semicolon) fprintf(f, "\n");
if(t->kind == TK_Semicolon) fprintf(f, "\n");
if(t->kind == TK_Keyword) fprintf(f, " ");
if(t[0].kind == TK_Identifier && token_array_iter_peek(&array, 0)->kind == TK_Identifier) fprintf(f, " ");
token_array_iter_peek(&array, 1);
}
arena_end_scratch();
}
int main(){
FILE *f = fopen("generated.c", "w");
assert(f);
String_Map map[] = {
{lit("Type"), lit("Decl")},
{lit("first"), lit("list_decl.first")},
{lit("last"), lit("list_decl.last")},
{lit("remove"), lit("decl_list_remove")},
{lit("push_front"), lit("decl_dll_list_push_front")},
{lit("push"), lit("decl_dll_list_push")},
};
output_template(f, lit("dllqueue.c"), map, buff_cap(map));
fclose(f);
}

View File

@@ -1,33 +0,0 @@
New_Data_Type::typedef int;
CONST_VAL::const 324;
Ideas::enum{
One,
Two,
Three
}
Data::struct{
first: int;
second: int;
idea: Ideas;
}
function_call::(first_param: Data*, second_param: int[32]){
first_param.first = 10;
first_param.second = 10;
first_param.idea = Ideas.One;
p:= first_param;
for i in 0...32 {
second_param[i] = i;
}
for i := 0; i < 32; i++ {
second_param[i] = i;
}
return p;
}

6
lex.c
View File

@@ -86,7 +86,7 @@ typedef enum Token_Kind{
TK_BitAnd, TK_BitAnd,
TK_BitOr, TK_BitOr,
TK_BitXor, TK_Pointer,
TK_And, TK_And,
TK_Or, TK_Or,
TK_FirstLogical = TK_BitAnd, TK_FirstLogical = TK_BitAnd,
@@ -324,7 +324,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
case ';': t.kind = TK_Semicolon; break; case ';': t.kind = TK_Semicolon; break;
case '#': t.kind = TK_Pound; break; case '#': t.kind = TK_Pound; break;
CASE2('!', TK_Not, TK_NotEquals); CASE2('!', TK_Not, TK_NotEquals);
CASE2('^', TK_BitXor, TK_XorAssign); CASE2('^', TK_Pointer, TK_XorAssign);
CASE2('=', TK_Assign, TK_Equals); CASE2('=', TK_Assign, TK_Equals);
CASE2('*', TK_Mul, TK_MulAssign); CASE2('*', TK_Mul, TK_MulAssign);
CASE2('%', TK_Mod, TK_ModAssign); CASE2('%', TK_Mod, TK_ModAssign);
@@ -584,7 +584,7 @@ global const char *token_kind_string[] = {
[TK_Mod] = "%", [TK_Mod] = "%",
[TK_BitAnd] = "&", [TK_BitAnd] = "&",
[TK_BitOr] = "|", [TK_BitOr] = "|",
[TK_BitXor] = "^", [TK_Pointer] = "^",
[TK_Neg] = "~", [TK_Neg] = "~",
[TK_Not] = "!", [TK_Not] = "!",
[TK_OpenParen] = "(", [TK_OpenParen] = "(",

View File

@@ -5,11 +5,12 @@
#include "new_parse.cpp" #include "new_parse.cpp"
#include "new_type.cpp" #include "new_type.cpp"
#include "new_resolve.cpp" #include "new_resolve.cpp"
#include "cgenerate.cpp"
int main(){ int main(){
test_os_memory(); test_os_memory();
thread_ctx_init(); thread_ctx_init();
test_gen();
test_unicode(); test_unicode();
test_resolve(); test_resolve();
test_types(); test_types();
@@ -21,5 +22,3 @@ int main(){
test_intern_table(); test_intern_table();
lex_test(); lex_test();
} }

View File

@@ -27,6 +27,10 @@ struct Parse_Ctx:Lexer{
Token empty_token; Token empty_token;
S64 indent; S64 indent;
Intern_String intern(String string){
return intern_string(&interns, string);
}
void init(Allocator *perm_allocator, Allocator *heap_allocator){ void init(Allocator *perm_allocator, Allocator *heap_allocator){
perm = perm_allocator; perm = perm_allocator;
heap = heap_allocator; heap = heap_allocator;
@@ -85,6 +89,7 @@ struct Ast{
Token *pos; Token *pos;
}; };
struct Ast_Resolved_Type;
struct Ast_Typespec; struct Ast_Typespec;
struct Ast_Expr:Ast{ struct Ast_Expr:Ast{
union{ union{
@@ -94,13 +99,13 @@ struct Ast_Expr:Ast{
Token_Kind op; Token_Kind op;
Ast_Expr *expr; Ast_Expr *expr;
}unary; }unary;
struct{ struct{
Token_Kind op; Token_Kind op;
Ast_Expr *left; Ast_Expr *left;
Ast_Expr *right; Ast_Expr *right;
} binary; } binary;
struct{ struct{
Ast_Resolved_Type *type;
Ast_Typespec *typespec; Ast_Typespec *typespec;
Array<Ast_Expr *> exprs; Array<Ast_Expr *> exprs;
}compound; }compound;
@@ -124,12 +129,19 @@ struct Ast_Expr:Ast{
}; };
}; };
struct Ast_Block : Ast {
Array<Ast *> stmts;
};
struct Ast_Lambda : Ast_Expr { struct Ast_Lambda : Ast_Expr {
Array<Ast_Expr *> params; Array<Ast_Expr *> params;
Ast_Typespec *ret; Ast_Typespec *ret;
Ast_Block *block;
}; };
struct Ast_Resolved_Type;
struct Ast_Typespec:Ast{ struct Ast_Typespec:Ast{
Ast_Resolved_Type *resolved_type;
union{ union{
Ast_Typespec *base; Ast_Typespec *base;
Intern_String name; Intern_String name;
@@ -148,10 +160,6 @@ struct Ast_Decl:Ast{
Ast_Typespec *typespec; Ast_Typespec *typespec;
Ast_Expr *expr; Ast_Expr *expr;
}var; }var;
struct{
Array<Ast_Decl*> args;
Ast_Typespec *ret;
}func;
}; };
}; };
@@ -164,10 +172,10 @@ 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 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){

View File

@@ -26,7 +26,6 @@ enum Token_Kind{
TK_BitAnd, TK_BitAnd,
TK_BitOr, TK_BitOr,
TK_BitXor,
TK_And, TK_And,
TK_Or, TK_Or,
TK_FirstLogical = TK_BitAnd, TK_FirstLogical = TK_BitAnd,
@@ -83,7 +82,7 @@ enum Token_Kind{
TK_Integer, TK_Integer,
TK_Keyword, TK_Keyword,
TK_Pointer = TK_BitXor, TK_Pointer,
TK_Dereference, TK_Dereference,
}; };
@@ -172,7 +171,7 @@ lex_set_len(Lex_Stream *s, Token *token){
function void function void
lex_set_keywords(Lexer *lexer, Array<String> keywords){ lex_set_keywords(Lexer *lexer, Array<String> keywords){
Intern_String keyword = {}; Intern_String keyword = {};
Iter(keywords){ For(keywords){
keyword = intern_string(&lexer->interns, *it); keyword = intern_string(&lexer->interns, *it);
if(it == keywords.begin()) if(it == keywords.begin())
lexer->interns.first_keyword = keyword.str; lexer->interns.first_keyword = keyword.str;
@@ -241,27 +240,27 @@ lex_parse_string(Lex_Stream *s, Token *t, U8 c){
} }
} }
#define CASE2(op, OpName, Assign) \ #define CASE2(op, OpName, Assign) \
case op: \ case op: \
if (lexc(s) == '=') { \ if (lexc(s) == '=') { \
lex_advance(s); \ lex_advance(s); \
t.kind = Assign; \ t.kind = Assign; \
} else { \ } else { \
t.kind = OpName; \ t.kind = OpName; \
} \ } \
break break
#define CASE3(op, OpName, Assign, Incr) \ #define CASE3(op, OpName, Assign, Incr) \
case op: \ case op: \
if (lexc(s) == '=') { \ if (lexc(s) == '=') { \
lex_advance(s); \ lex_advance(s); \
t.kind = Assign; \ t.kind = Assign; \
} else if (lexc(s) == op) { \ } else if (lexc(s) == op) { \
lex_advance(s); \ lex_advance(s); \
t.kind = Incr; \ t.kind = Incr; \
} else { \ } else { \
t.kind = OpName; \ t.kind = OpName; \
} \ } \
break break
function void function void
lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
@@ -287,8 +286,8 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
case '~': t.kind = TK_Neg; break; case '~': t.kind = TK_Neg; break;
case '?': t.kind = TK_Question; break; case '?': t.kind = TK_Question; break;
case '#': t.kind = TK_Pound; break; case '#': t.kind = TK_Pound; break;
case '^': t.kind = TK_Pointer; break;
CASE2('!', TK_Not, TK_NotEquals); CASE2('!', TK_Not, TK_NotEquals);
CASE2('^', TK_BitXor, TK_XorAssign);
CASE2('=', TK_Assign, TK_Equals); CASE2('=', TK_Assign, TK_Equals);
CASE2('*', TK_Mul, TK_MulAssign); CASE2('*', TK_Mul, TK_MulAssign);
CASE2('%', TK_Mod, TK_ModAssign); CASE2('%', TK_Mod, TK_ModAssign);
@@ -510,7 +509,12 @@ lex_make(Allocator *token_string_arena, Allocator *map_allocator){
function void function void
lex_restream(Lexer *lexer, String istream, String file){ lex_restream(Lexer *lexer, String istream, String file){
lexer->stream = {istream, 0, istream.str, file, 0}; lexer->stream = {};
lexer->stream.stream = istream;
lexer->stream.line_begin = istream.str;
lexer->stream.file = file;
lexer->tokens.clear(); lexer->tokens.clear();
lexer->token_iter = 0; lexer->token_iter = 0;
lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream); lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream);
@@ -587,7 +591,7 @@ token_kind_string(Token_Kind kind){
case TK_Mod: return "%"_s; case TK_Mod: return "%"_s;
case TK_BitAnd: return "&"_s; case TK_BitAnd: return "&"_s;
case TK_BitOr: return "|"_s; case TK_BitOr: return "|"_s;
case TK_BitXor: return "^"_s; case TK_Pointer: return "^"_s;
case TK_Neg: return "~"_s; case TK_Neg: return "~"_s;
case TK_Not: return "!"_s; case TK_Not: return "!"_s;
case TK_OpenParen: return "("_s; case TK_OpenParen: return "("_s;

View File

@@ -165,9 +165,19 @@ parse_optional_type(){
return result; return result;
} }
/*
function Ast_Block *
parse_block(){
Ast_Block *result = 0;
if(token_match(TK_NewScope)){
}
return result;
}
*/
function Ast_Lambda * function Ast_Lambda *
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently 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; Scratch scratch;
Array<Ast_Expr *> params = {scratch}; Array<Ast_Expr *> params = {scratch};
// @Note(Krzosa): No need to guard against "()" // @Note(Krzosa): No need to guard against "()"
@@ -186,6 +196,8 @@ parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typesp
} }
} }
token_expect(TK_CloseParen); token_expect(TK_CloseParen);
//Ast_Block *block = parse_block();
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type()); Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
return result; return result;
} }
@@ -196,7 +208,7 @@ null_denotation(Token *token){
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_Pointer : 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);
@@ -237,7 +249,7 @@ left_binding_power(Token_Kind kind){
function S64 function S64
postfix_binding_power(Token_Kind kind){ postfix_binding_power(Token_Kind kind){
switch(kind){ switch(kind){
case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1; case TK_Increment: case TK_Decrement: case TK_Pointer: case TK_OpenBracket: return 1;
default: return 0; default: return 0;
} }
} }
@@ -260,7 +272,7 @@ parse_expr(S64 rbp){
for(;;){ for(;;){
token = token_get(); token = token_get();
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_BitXor || token->kind == TK_OpenBracket)){ if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_Pointer || token->kind == TK_OpenBracket)){
token_next(); token_next();
if(token->kind == TK_OpenBracket){ if(token->kind == TK_OpenBracket){
Ast_Expr *index = parse_expr(); Ast_Expr *index = parse_expr();
@@ -312,11 +324,11 @@ expr_eval(Ast_Expr *expr){
return 0; return 0;
} }
#define TEST_PARSER() \ #define TEST_PARSER() \
Scratch scratch(thread_ctx.scratch);\ Scratch scratch(thread_ctx.scratch); \
Parse_Ctx ctx = {}; \ Parse_Ctx ctx = {}; \
ctx.init(scratch, scratch); \ ctx.init(scratch, scratch); \
pctx = &ctx pctx = &ctx
function void function void
test_parse_expr(){ test_parse_expr(){
@@ -330,7 +342,7 @@ test_parse_expr(){
exprs.add({"4*5+5"_s, 4*5+5}); exprs.add({"4*5+5"_s, 4*5+5});
exprs.add({"4+5+5+3"_s, 4+5+5+3}); exprs.add({"4+5+5+3"_s, 4+5+5+3});
Iter(exprs){ For(exprs){
lex_restream(&ctx, it->str, "test_expr"_s); lex_restream(&ctx, it->str, "test_expr"_s);
Ast_Expr *result = parse_expr(); Ast_Expr *result = parse_expr();
S64 val = expr_eval(result); S64 val = expr_eval(result);
@@ -341,12 +353,11 @@ test_parse_expr(){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Parsing declarations // Parsing declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [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_BitXor)){ if(token_match(TK_Pointer)){
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;

View File

@@ -12,7 +12,7 @@ struct Sym{
Intern_String name; Intern_String name;
Sym_Kind kind; Sym_Kind kind;
Ast_Decl *decl; Ast_Decl *decl;
Type *type; Ast_Resolved_Type *type;
union{ union{
S64 int_val; S64 int_val;
Intern_String intern_val; Intern_String intern_val;
@@ -20,7 +20,7 @@ struct Sym{
}; };
struct Operand{ struct Operand{
Type *type; Ast_Resolved_Type *type;
bool is_const; bool is_const;
union { union {
S64 int_val; S64 int_val;
@@ -46,7 +46,7 @@ sym_get(Intern_String name){
} }
function Sym * function Sym *
sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){ sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast_Decl *decl){
Sym *result = exp_alloc_type(pctx->perm, Sym); Sym *result = exp_alloc_type(pctx->perm, Sym);
result->name = name; result->name = name;
result->kind = kind; result->kind = kind;
@@ -57,7 +57,7 @@ sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
global Ast_Decl empty_decl = {}; global Ast_Decl empty_decl = {};
function void function void
sym_insert_builtin_type(String name, Type *type){ sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
Intern_String string = intern_string(&pctx->interns, name); Intern_String string = intern_string(&pctx->interns, name);
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl); Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
sym_insert(sym); sym_insert(sym);
@@ -87,12 +87,10 @@ sym_insert_builtins(){
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl); Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
sym_insert(sym); sym_insert(sym);
} }
} }
function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0); function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0);
function Type * function Ast_Resolved_Type *
eval_typespec(Ast_Typespec *ast){ eval_typespec(Ast_Typespec *ast){
if(!ast) return 0; if(!ast) return 0;
@@ -105,34 +103,36 @@ eval_typespec(Ast_Typespec *ast){
if(type_sym->kind != SYM_Type){ if(type_sym->kind != SYM_Type){
parsing_error(node->pos, "This identifier is not a type"); parsing_error(node->pos, "This identifier is not a type");
} }
return type_sym->type;
node->resolved_type = type_sym->type;
return node->resolved_type;
Ast_End(); Ast_End();
} }
Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){ Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
Scratch scratch; Scratch scratch;
Type *ret = eval_typespec(node->lambda->ret); Ast_Resolved_Type *ret = eval_typespec(node->lambda->ret);
Array<Type *> params = {scratch}; Array<Ast_Resolved_Type *> params = {scratch};
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec)); For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
Type *result = type_lambda(ret, params); node->resolved_type = type_lambda(ret, params);
return result; return node->resolved_type;
Ast_End(); Ast_End();
} }
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){ Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
Type *type = eval_typespec(node->base); Ast_Resolved_Type *type = eval_typespec(node->base);
Type *result = type_pointer(type); node->resolved_type = type_pointer(type);
return result; return node->resolved_type;
Ast_End(); Ast_End();
} }
Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){ Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
Type *type = eval_typespec(node->arr.base); Ast_Resolved_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");
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type int"); if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type [Int] is instead of type %s", type_names[expr.type->kind]);
Type *result = type_array(type, expr.int_val); node->resolved_type = type_array(type, expr.int_val);
return result; return node->resolved_type;
Ast_End(); Ast_End();
} }
invalid_default_case; invalid_default_case;
@@ -140,24 +140,26 @@ eval_typespec(Ast_Typespec *ast){
return 0; return 0;
} }
function Type * function Ast_Resolved_Type *
resolve_type_pair(Token *pos, Type *a, Type *b){ resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
Type *result = 0; Ast_Resolved_Type *result = 0;
if(!a && b) result = b; if(!a && b) result = b;
else if(a && !b) result = a; else if(a && !b) result = a;
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are null"); else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
else{ // a && b else{ // a && b
if(b->kind == TYPE_Null) result = a; if(b->kind == TYPE_Null) result = a;
else if(a->kind == TYPE_Null) result = b; else if(a->kind == TYPE_Null) result = b;
else if(a != b) parsing_error(pos, "Expression and type specification are differing"); else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
else result = a; // Types are the same else result = a; // Types are the same
} }
if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value");
return result; return result;
} }
function Operand function Operand
eval_expr(Ast_Expr *ast, Type *exp_compound_type){ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
switch(ast->kind){ switch(ast->kind){
Ast_Begin(AST_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}};
@@ -171,8 +173,57 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Ast_End(); Ast_End();
} }
Ast_Begin(AST_IDENT, Ast_Expr){
Sym *sym = sym_get(node->intern_val);
if(!sym){
parsing_error(node->pos, "Identifier is undefined");
}
// @note: check if null and rewrite the expression to match the expected type
Operand result = {};
if(sym->type->kind == TYPE_Null){
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
result.type = expected_type;
result.is_const = true;
if(expected_type == type_int){
result.int_val = 0;
node->kind = AST_INT;
node->int_val = 0;
}
else if(expected_type->kind == TYPE_Pointer){
result.int_val = 0;
node->kind = AST_IDENT;
node->intern_val = pctx->intern("null_pointer"_s);
}
else if(expected_type->kind == TYPE_Lambda){
result.int_val = 0;
node->kind = AST_IDENT;
node->intern_val = pctx->intern("null_lambda"_s);
}
else if(expected_type == type_bool){
result.int_val = 0;
node->kind = AST_IDENT;
node->intern_val = pctx->intern("false"_s);
}
else if(expected_type == type_string){
result.intern_val = pctx->intern(""_s);
node->kind = AST_STR;
node->intern_val = result.intern_val;
}
}
else{
result.type = sym->type;
result.is_const = sym->kind == SYM_Const ? true : false;
result.int_val = sym->int_val;
}
return result;
Ast_End();
}
Ast_Begin(AST_LAMBDA, Ast_Lambda){ Ast_Begin(AST_LAMBDA, Ast_Lambda){
Type *type = eval_typespec(ast_typespec_lambda(0, node)); Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
return {type, true}; return {type, true};
Ast_End(); Ast_End();
} }
@@ -188,28 +239,29 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
} }
Ast_Begin(AST_COMPOUND, Ast_Expr){ Ast_Begin(AST_COMPOUND, Ast_Expr){
Type *type = eval_typespec(node->compound.typespec); Ast_Resolved_Type *type = eval_typespec(node->compound.typespec);
Type *variable_type = exp_compound_type; Ast_Resolved_Type *variable_type = expected_type;
if(!type && variable_type) type = variable_type; if(!type && variable_type) type = variable_type;
else if(!variable_type && type); else if(!variable_type && type);
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type"); else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
node->compound.type = type;
if(type->kind == TYPE_Array){ if(type->kind == TYPE_Array){
if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type"); if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
Type *item_type = type->arr.base; Ast_Resolved_Type *item_type = type->arr.base;
For(node->compound.exprs){ For(node->compound.exprs){
assert(it[0]->kind == AST_COMPOUND_ITEM); assert(it[0]->kind == AST_COMPOUND_ITEM);
Ast_Expr *i = (Ast_Expr *)it[0]; Ast_Expr *i = (Ast_Expr *)it[0];
assert(i->kind == AST_COMPOUND_ITEM); assert(i->kind == AST_COMPOUND_ITEM);
if(i->compound_item.name) parsing_error(i->pos, "Invalid array indexing in compound expression"); if(i->compound_item.name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
if(i->compound_item.index){ if(i->compound_item.index){
Operand index_op = eval_expr(i->compound_item.index); Operand index_op = eval_expr(i->compound_item.index);
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant"); 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.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"); 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(i->compound_item.item); Operand expr = eval_expr(i->compound_item.item, item_type);
resolve_type_pair(i->pos, expr.type, item_type); resolve_type_pair(i->pos, expr.type, item_type);
} }
} }
@@ -220,20 +272,9 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Ast_End(); Ast_End();
} }
Ast_Begin(AST_IDENT, Ast_Expr){
Sym *sym = sym_get(node->intern_val);
if(!sym){
parsing_error(node->pos, "Identifier is undefined");
}
Operand result = {sym->type, sym->kind == SYM_Const ? true : false, {.int_val = sym->int_val}};
return result;
Ast_End();
}
Ast_Begin(AST_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); Ast_Resolved_Type *type = eval_typespec(node->cast.typespec);
if(type == expr.type) return expr; if(type == expr.type) return expr;
@@ -260,7 +301,7 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
Ast_Begin(AST_UNARY, Ast_Expr){ Ast_Begin(AST_UNARY, Ast_Expr){
Operand value = eval_expr(node->unary.expr); Operand value = eval_expr(node->unary.expr);
switch(node->unary.op){ switch(node->unary.op){
case TK_BitXor:{ case TK_Pointer:{
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer"); if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
Operand result = {value.type->base}; Operand result = {value.type->base};
return result; return result;
@@ -314,9 +355,9 @@ eval_decl(Ast *ast){
} }
Ast_Begin(AST_VAR, Ast_Decl){ Ast_Begin(AST_VAR, Ast_Decl){
Type *type = eval_typespec(node->var.typespec); Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{}; Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); Ast_Resolved_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);
sym_insert(sym); sym_insert(sym);
@@ -324,12 +365,12 @@ eval_decl(Ast *ast){
} }
Ast_Begin(AST_CONST, Ast_Decl){ Ast_Begin(AST_CONST, Ast_Decl){
Type *type = eval_typespec(node->var.typespec); Ast_Resolved_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);
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");
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type); Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node); Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
if(resolved_type == type_int) sym->int_val = expr.int_val; if(resolved_type == type_int) sym->int_val = expr.int_val;

View File

@@ -1,4 +1,4 @@
enum Type_Kind{ enum Ast_Resolved_Type_Kind{
TYPE_None, TYPE_None,
TYPE_Null, TYPE_Null,
TYPE_Int, TYPE_Int,
@@ -8,41 +8,41 @@ enum Type_Kind{
TYPE_Void, TYPE_Void,
TYPE_Pointer, TYPE_Pointer,
TYPE_Array, TYPE_Array,
TYPE_Func, TYPE_Lambda,
TYPE_Struct, TYPE_Struct,
TYPE_Union, TYPE_Union,
TYPE_Enum, TYPE_Enum,
}; };
const char *type_names[] = { const char *type_names[] = {
"[Invalid Type]", "[Invalid Ast_Resolved_Type]",
"[TYPE_Null]", "[Null]",
"[TYPE_Int]", "[Int]",
"[TYPE_Bool]", "[Bool]",
"[TYPE_Unsigned]", "[Unsigned]",
"[TYPE_String]", "[String]",
"[TYPE_Void]", "[Void]",
"[TYPE_Pointer]", "[Pointer]",
"[TYPE_Array]", "[Array]",
"[TYPE_Func]", "[Lambda]",
"[TYPE_Struct]", "[Struct]",
"[TYPE_Union]", "[Union]",
"[TYPE_Enum]", "[Enum]",
}; };
struct Type{ struct Ast_Resolved_Type{
Type_Kind kind; Ast_Resolved_Type_Kind kind;
SizeU size; SizeU size;
SizeU align; SizeU align;
union{ union{
Type *base; Ast_Resolved_Type *base;
struct{ struct{
Type *base; Ast_Resolved_Type *base;
SizeU size; SizeU size;
}arr; }arr;
struct{ struct{
Type *ret; Ast_Resolved_Type *ret;
Array<Type*> args; Array<Ast_Resolved_Type*> args;
}func; }func;
}; };
}; };
@@ -50,39 +50,39 @@ struct Type{
const SizeU pointer_size = sizeof(SizeU); const SizeU pointer_size = sizeof(SizeU);
const SizeU pointer_align = __alignof(SizeU); const SizeU pointer_align = __alignof(SizeU);
global Type type__null = {TYPE_Null}; global Ast_Resolved_Type type__null = {TYPE_Null};
global Type type__void = {TYPE_Void}; global Ast_Resolved_Type type__void = {TYPE_Void};
global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)}; global Ast_Resolved_Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
global Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)}; global Ast_Resolved_Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
global Type type__string = {TYPE_String, sizeof(String), __alignof(String)}; global Ast_Resolved_Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
global Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)}; global Ast_Resolved_Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
global Type *type_void = &type__void; global Ast_Resolved_Type *type_void = &type__void;
global Type *type_int = &type__int; global Ast_Resolved_Type *type_int = &type__int;
global Type *type_unsigned = &type__unsigned; global Ast_Resolved_Type *type_unsigned = &type__unsigned;
global Type *type_string = &type__string; global Ast_Resolved_Type *type_string = &type__string;
global Type *type_bool = &type__bool; global Ast_Resolved_Type *type_bool = &type__bool;
global Type *type_null = &type__null; global Ast_Resolved_Type *type_null = &type__null;
function Type * function Ast_Resolved_Type *
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){ type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){
Type *result = exp_alloc_type(allocator, Type); Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type);
result->kind = kind; result->kind = kind;
result->size = size; result->size = size;
result->align = align; result->align = align;
return result; return result;
} }
function Type * function Ast_Resolved_Type *
type_copy(Allocator *a, Type *type){ type_copy(Allocator *a, Ast_Resolved_Type *type){
Type *result = exp_alloc_type(a, Type); Ast_Resolved_Type *result = exp_alloc_type(a, Ast_Resolved_Type);
memory_copy(result, type, sizeof(Type)); memory_copy(result, type, sizeof(Ast_Resolved_Type));
return result; return result;
} }
function Type * function Ast_Resolved_Type *
type_pointer(Type *base){ type_pointer(Ast_Resolved_Type *base){
Type *result = (Type *)map_get(&pctx->type_map, (void *)base); Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base);
if(!result){ if(!result){
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
result->base = base; result->base = base;
@@ -92,10 +92,10 @@ type_pointer(Type *base){
return result; return result;
} }
function Type * function Ast_Resolved_Type *
type_array(Type *base, SizeU size){ type_array(Ast_Resolved_Type *base, SizeU size){
U64 hash = hash_mix(hash_ptr(base), hash_u64(size)); U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
Type *result = (Type *)map_get_u64(&pctx->type_map, hash); Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash);
if(result){ if(result){
assert(result->kind == TYPE_Array); assert(result->kind == TYPE_Array);
assert(result->arr.size == size); assert(result->arr.size == size);
@@ -110,20 +110,20 @@ type_array(Type *base, SizeU size){
return result; return result;
} }
function Type * function Ast_Resolved_Type *
type_lambda(Type *ret, Array<Type *> args){ type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_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); Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash);
if(result){ if(result){
assert(result->kind == TYPE_Func); assert(result->kind == TYPE_Lambda);
assert(result->func.ret == ret); assert(result->func.ret == ret);
assert(result->func.args.len == args.len); assert(result->func.args.len == args.len);
return result; return result;
} }
result = type_new(pctx->perm, TYPE_Func, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_Lambda, pointer_size, pointer_align);
result->func.ret = ret; result->func.ret = ret;
result->func.args = args.tight_copy(pctx->perm); result->func.args = args.tight_copy(pctx->perm);
map_insert_u64(&pctx->type_map, hash, result); map_insert_u64(&pctx->type_map, hash, result);
@@ -138,33 +138,33 @@ test_types(){
ctx.init(scratch, scratch); ctx.init(scratch, scratch);
pctx = &ctx; pctx = &ctx;
Type *array_type1 = type_array(type_int, 32); Ast_Resolved_Type *array_type1 = type_array(type_int, 32);
Type *array_type2 = type_array(type_int, 32); Ast_Resolved_Type *array_type2 = type_array(type_int, 32);
Type *array_type3 = type_array(type_int, 48); Ast_Resolved_Type *array_type3 = type_array(type_int, 48);
assert(array_type1 == array_type2); assert(array_type1 == array_type2);
assert(array_type2 != array_type3); assert(array_type2 != array_type3);
Type *pointer_type1 = type_pointer(type_int); Ast_Resolved_Type *pointer_type1 = type_pointer(type_int);
Type *pointer_type2 = type_pointer(type_int); Ast_Resolved_Type *pointer_type2 = type_pointer(type_int);
assert(pointer_type2 == pointer_type1); assert(pointer_type2 == pointer_type1);
Type *pointer_type3 = type_pointer(pointer_type1); Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1);
Type *pointer_type4 = type_pointer(pointer_type2); Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2);
assert(pointer_type3 != pointer_type1); assert(pointer_type3 != pointer_type1);
assert(pointer_type3 == pointer_type4); assert(pointer_type3 == pointer_type4);
Array<Type*> types = {scratch}; Array<Ast_Resolved_Type*> types = {scratch};
types.add(type_array(type_int, 32)); types.add(type_array(type_int, 32));
Type *func_type1 = type_lambda(types[0], types); Ast_Resolved_Type *func_type1 = type_lambda(types[0], types);
Type *func_type2 = type_lambda(types[0], types); Ast_Resolved_Type *func_type2 = type_lambda(types[0], types);
assert(func_type1 == func_type2); assert(func_type1 == func_type2);
Array<Type*> types2 = {scratch}; Array<Ast_Resolved_Type*> types2 = {scratch};
{ {
types2.add(type_array(type_int, 32)); types2.add(type_array(type_int, 32));
types2.add(type_int); types2.add(type_int);
} }
types.add(type_int); types.add(type_int);
Type *func_type3 = type_lambda(types[0], types); Ast_Resolved_Type *func_type3 = type_lambda(types[0], types);
Type *func_type4 = type_lambda(types[0], types2); Ast_Resolved_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);
} }

294
output.cc
View File

@@ -1,294 +0,0 @@
(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2)))
(4+(2*53))
((4+2)*53)
(++5)
(--5)
(-5)
(+5)
(sizeof(32)+sizeof(S32*))
((S64**)5)
(((S64)5)+3)
((534>43)?435:42)
struct Thing{
int test;
};
S32 thing = 100;
(thing=(thing+10));
(++thing);
{
S32 thing_scoped = 10;
(thing_scoped+=10);
}
typedef struct OpenGL OpenGL;
typedef struct OS_Memory OS_Memory;
typedef struct Arena Arena;
typedef struct String String;
typedef struct Token Token;
typedef struct Lex_Stream Lex_Stream;
typedef struct Expr Expr;
typedef struct AST_Node AST_Node;
typedef struct Parser_Error Parser_Error;
typedef struct Scope Scope;
typedef struct Parser Parser;
struct test{
struct Array_Block{
Array_Block (*next);
Based_Type_Represent (data[size]);
};
struct Array{
Array_Block first;
Array_Block (*last);
S64 block;
S64 len;
};
function Based_Type_Represent array_make(Arena (*arena)){
Test_Type thing;
Based_Type_Represent result;
((result.arena)=arena);
((result.last)=(&(result.first)));
return result;
}
function void array_push(Array (*array), Based_Type_Represent (*item)){
if (((array->len)+1)>size){
assert((array->len));
Array_Block (*block) = ((Thing)arena_push_struct(((array->arena),sizeof(Array_Block))));
((array->last)=(((array->last).next)=block));
((array->len)=0);
((array->block)+=1);
}
(((array->last).data)[(++(array->len))]=(*item));
}
};
struct OpenGL{
void (*glVertexAttribPointer)(GLuint, GLint, GLenumGLenum, GLboolean, GLsizei, GLvoid *);
void (*glBindTexture)(GLenum, GLuint);
void (*glDrawArrays)(GLenumGLenum, GLint, GLsizei);
int (*(test_array[10]));
Things (*thing);
S64 thing_cap;
S64 thing_len;
};
struct OS_Memory{
void (*data);
SizeU commit;
SizeU reserve;
};
struct Arena{
OS_Memory memory;
U64 len;
U64 alignment;
};
struct String{
U8 (*str);
S64 len;
};
typedef String Intern_String;
typedef enum Token_Kind{
TK_End,
TK_Mul,
TK_Div,
TK_Add,
TK_Sub,
TK_Mod,
TK_BitAnd,
TK_BitOr,
TK_BitXor,
TK_Neg,
TK_Not,
TK_OpenParen,
TK_CloseParen,
TK_OpenBrace,
TK_CloseBrace,
TK_OpenBracket,
TK_CloseBracket,
TK_Comma,
TK_Pound,
TK_Question,
TK_ThreeDots,
TK_Semicolon,
TK_Dot,
TK_LesserThen,
TK_GreaterThen,
TK_Colon,
TK_Assign,
TK_DivAssign,
TK_MulAssign,
TK_ModAssign,
TK_SubAssign,
TK_AddAssign,
TK_AndAssign,
TK_OrAssign,
TK_XorAssign,
TK_LeftShiftAssign,
TK_RightShiftAssign,
TK_DoubleColon,
TK_At,
TK_Decrement,
TK_Increment,
TK_PostDecrement,
TK_PostIncrement,
TK_LesserThenOrEqual,
TK_GreaterThenOrEqual,
TK_Equals,
TK_And,
TK_Or,
TK_NotEquals,
TK_LeftShift,
TK_RightShift,
TK_Arrow,
TK_ExprSizeof,
TK_DocComment,
TK_Comment,
TK_Identifier,
TK_StringLit,
TK_U8Lit,
TK_Character,
TK_Error,
TK_Float,
TK_Int,
TK_Keyword,
}Token_Kind;
struct Token{
Token_Kind kind;
String string;
union{
S64 integer_val;
String error_val;
Intern_String intern_val;
};
String file;
S64 line;
U8 (*line_begin);
};
struct Lex_Stream{
U8 (*stream);
U8 (*line_begin);
String filename;
S64 line;
};
typedef enum Expr_Kind{
EK_None,
EK_Atom,
EK_Unary,
EK_Binary,
EK_Ternary,
EK_Cast,
EK_List,
EK_Call,
EK_Index,
}Expr_Kind;
struct Expr{
Expr_Kind kind;
Token (*token);
Expr (*next);
union{
struct{
AST_Node (*type);
Expr (*expr);
}cast_val;
struct{
Expr (*first);
Expr (*last);
}list;
struct{
Expr (*atom);
Expr (*list);
}call;
struct{
Expr (*atom);
Expr (*index);
}index;
struct{
Expr (*expr);
}unary;
struct{
Expr (*left);
Expr (*right);
}binary;
struct{
Expr (*cond);
Expr (*on_true);
Expr (*on_false);
}ternary;
};
};
typedef enum AST_Kind{
AK_None,
AK_BaseType,
AK_Typedef,
AK_Enum,
AK_Struct,
AK_Union,
AK_Note,
AK_List,
AK_Pointer,
AK_Array,
AK_Function,
AK_Variable,
AK_EnumChild,
}AST_Kind;
struct AST_Node{
AST_Kind kind;
Token (*pos);
Intern_String name;
AST_Node (*next);
AST_Node (*next_scope);
AST_Node (*first_note);
AST_Node (*last_note);
AST_Node (*first_child);
AST_Node (*last_child);
union{
SizeU base_type_size;
AST_Node (*pointer);
AST_Node (*typedef_type);
AST_Node (*variable_type);
AST_Node (*func_return_type);
};
};
struct Parser_Error{
Parser_Error (*next);
String message;
Token (*token);
};
struct Scope{
Scope (*next);
AST_Node (*first);
AST_Node (*last);
};
struct Parser{
Arena main_arena;
Arena intern_table_arena;
Arena symbol_table_arena;
Scope (*scope_free_list);
Scope (*scope_stack);
Scope (*global_scope);
S64 symbols_inserted;
S64 symbols_count;
AST_Node (*symbols);
Intern_String (*interns);
S64 interns_in_bytes;
S64 interns_inserted;
S64 interns_count;
U8 (*first_keyword);
U8 (*last_keyword);
Parser_Error default;
Parser_Error error;
};

View File

@@ -1017,7 +1017,7 @@ eval_expr(Expr *expr){
case TK_LesserThen: return left < right; break; case TK_LesserThen: return left < right; break;
case TK_BitAnd: return left & right; break; case TK_BitAnd: return left & right; break;
case TK_BitOr: return left | right; break; case TK_BitOr: return left | right; break;
case TK_BitXor: return left ^ right; break; case TK_Pointer: return left ^ right; break;
case TK_And: return left && right; break; case TK_And: return left && right; break;
case TK_Or: return left || right; break; case TK_Or: return left || right; break;
case TK_LeftShift: return left << right; break; case TK_LeftShift: return left << right; break;

286
test.cc
View File

@@ -1,286 +0,0 @@
Thing :: const: *U32 = 0;
CONST_VAL::const = 185210591;
new_function::(Thing:[32]U32): U32;
@test(size = 4096)
OpenGL :: struct{
glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, *GLvoid);
glBindTexture: (GLenum, GLuint);
glDrawArrays: (GLenum, GLint, GLsizei);
test_array: [10]*int;
thing : *Things;
thing_cap: S64;
thing_len: S64;
}
OS_Memory::struct{
data: *void;
commit: SizeU;
reserve: SizeU;
}
Arena::struct{
@using memory: OS_Memory;
len: U64;
alignment: U64;
}
String::struct{
str: *U8;
len: S64;
}
Intern_String::typedef = String;
//CONST_VALUE::const = 121591;
@stringify
@prefix="TK_"
Token_Kind::enum{
@str="End of stream" End,
@str="*" Mul,
@str="/" Div,
@str="+" Add,
@str="-" Sub,
@str="%" Mod,
@str="&" BitAnd,
@str="|" BitOr,
@str="^" BitXor,
@str="~" Neg,
@str="!" Not,
@str="(" OpenParen,
@str=" " CloseParen,
@str="{" OpenBrace,
@str="}" CloseBrace,
@str="[" OpenBracket,
@str="]" CloseBracket,
@str="," Comma,
@str="#" Pound,
@str="?" Question,
@str="..." ThreeDots,
@str=";" Semicolon,
@str="." Dot,
@str="<" LesserThen,
@str=">" GreaterThen,
@str=":" Colon,
@str="=" Assign,
@str="/=" DivAssign,
@str="*=" MulAssign,
@str="%=" ModAssign,
@str="-=" SubAssign,
@str="+=" AddAssign,
@str="&=" AndAssign,
@str="|=" OrAssign,
@str="^=" XorAssign,
@str="<<=" LeftShiftAssign,
@str=">>=" RightShiftAssign,
@str="::" DoubleColon,
@str="@" At,
@str="--" Decrement,
@str="++" Increment,
@str="--" PostDecrement,
@str="++" PostIncrement,
@str="<=" LesserThenOrEqual,
@str=">=" GreaterThenOrEqual,
@str="==" Equals,
@str="&&" And,
@str="||" Or,
@str="!=" NotEquals,
@str="<<" LeftShift,
@str=">>" RightShift,
@str="->" Arrow,
@str="sizeof" ExprSizeof,
DocComment,
Comment,
Identifier,
StringLit,
U8Lit,
Character,
Error,
Float,
Int,
Keyword,
}
@array(type=block)
Token::struct{
kind:Token_Kind;
@using string:String;
union{
integer_val:S64;
error_val:String;
intern_val:Intern_String;
}
file:String;
line:S64;
line_begin:*U8;
}
Lex_Stream::struct{
stream: *U8;
line_begin: *U8;
filename: String;
line: S64;
}
@prefix="EK_"
Expr_Kind::enum{
None,
Atom,
Unary,
Binary,
Ternary,
Cast,
List,
Call,
Index,
}
Expr:: struct{
kind: Expr_Kind;
token: *Token;
next : *Expr;
union{
cast_val: struct{
type: *AST_Node;
expr: *Expr;
}
list: struct{
first: *Expr;
last: *Expr;
}
call: struct{
atom: *Expr;
list: *Expr;
}
index: struct{
atom: *Expr;
index: *Expr;
}
unary: struct{
expr: *Expr ;
}
binary: struct{
left: *Expr ;
right: *Expr ;
}
ternary: struct{
cond: *Expr ;
on_true: *Expr;
on_false: *Expr;
}
}
}
@prefix="AK_"
AST_Kind::enum{
None,
BaseType,
Typedef,
Enum,
Struct,
Union,
Note,
List,
Pointer,
Array,
Function,
Variable,
EnumChild,
}
AST_Node::struct{
kind: AST_Kind;
pos : *Token;
name: Intern_String;
next: *AST_Node;
next_scope: *AST_Node;
first_note: *AST_Node;
last_note: *AST_Node;
first_child: *AST_Node;
last_child: *AST_Node;
union{
base_type_size: SizeU;
pointer: *AST_Node;
typedef_type: *AST_Node;
variable_type: *AST_Node;
func_return_type: *AST_Node;
}
}
Parser_Error :: struct{
next: *Parser_Error;
message: String;
token : *Token;
}
Scope :: struct{
next : *Scope;
first: *AST_Node;
last : *AST_Node;
}
Parser :: struct{
main_arena: Arena;
intern_table_arena: Arena;
symbol_table_arena: Arena;
scope_free_list: Scope;
scope_stack: Scope;
global_scope: Scope;
symbols_inserted: S64;
symbols_count: S64;
symbols: AST_Node;
interns: Intern_String;
interns_in_bytes: S64;
interns_inserted: S64;
interns_count: S64;
first_keyword: U8;
last_keyword: U8;
//@map(type="sparse") symbols: AST_Node;
// @Todo(Krzosa): This adds default to function name currently
// And it's hard to anything else sort of except adding
// a variable of _var_name_lower_with_ or something
@sllqueue default: Parser_Error;
// This works ok
@sllqueue error: Parser_Error;
//@using token_array: Tokens;
}
function_test::(a:U32, b:U32):*U32{
scratch := get_scratch();
defer{release_scratch(scratch);}
if a > 10 {
c := b + 10;
b = c;
}
else if a == 20 {
d := 1241215;
b = d;
}
else {
c := b+20;
b = c;
}
for {
c: U32 = b + 1;
}
for i:=0; i < 10; i++ {
print(i);
}
return *b;
}

View File

@@ -1,31 +0,0 @@
Thing :: struct {
arena: *Arena;
}
main :: (argc: int, argv: **char): int {
thing: int = proc(&argc);
arena: Arena;
for i:=0; i < 10; i++ {
}
}
proc :: (thing: *int): *int {
thing = SCRATCH_COUNT + 10;
return thing;
}
Arena :: struct {
cap: int;
len: int;
data: *void;
}
Thread_Ctx :: struct {
arenas: [SCRATCH_COUNT]Arena;
}
SCRATCH_COUNT::const = 3;

View File

@@ -1,6 +1,4 @@
/* /*
Player :: struct Player :: struct
id : int id : int
name: String name: String
@@ -12,7 +10,7 @@ compound_of_struct: Player = {
second_compound_syntax := :Player{...} second_compound_syntax := :Player{...}
max :: (a: int, b: int) { if a > b then return a; return b; } max_folding :: (a: int, b: int) { if a > b { return a; } return b; }
max :: (a: int, b: int) max :: (a: int, b: int)
if a > b then return a if a > b then return a
@@ -22,22 +20,34 @@ max :: (a: int, b: int)
{ and } - treated as new line scope and end of new line scope { and } - treated as new line scope and end of new line scope
*/ */
//-----------------------------------------------------------------------------
// Function types
//-----------------------------------------------------------------------------
test_function :: (thing: int): ^int test_function :: (thing: int): ^int
function_type: (thing: int): ^int = test_function
const_function_alias :: test_function
null_function: (t: int): ^int = null
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Booleans // Booleans
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
boolean: bool = true boolean: bool = true
value_of_bool: int = cast(boolean: int) value_of_bool: int = cast(boolean: int)
base := null
//-----------------------------------------------------------------------------
// Nulls
//-----------------------------------------------------------------------------
int_null: int = null
str_null: String = null
bool_null: bool = null
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Compound expressions // 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] = null,
[1] = 1, [1] = 1,
[31] = 31, [31] = 31,
} }
@@ -61,8 +71,8 @@ implicit_str :: "Hello world"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Pointers // Pointers
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
pointer: ^int = cast(null: ^int) pointer1: ^int = null
pointer2: ^int = null pointer2: ^int = pointer1
pointer3: ^^int = null pointer3: ^^int = null
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

157
type.c
View File

@@ -1,157 +0,0 @@
typedef struct Type Type;
typedef enum Type_Kind{
TYPE_None,
TYPE_Incomplete,
TYPE_Int,
TYPE_Char,
TYPE_Void,
TYPE_Pointer,
TYPE_Array,
TYPE_Func,
TYPE_Struct,
TYPE_Union,
TYPE_Enum,
}Type_Kind;
struct Type{
Type_Kind kind;
SizeU size;
SizeU align;
struct{
Type *base;
}pointer;
struct{
Type *base;
SizeU size;
}array;
struct{
Type **params;
S32 count;
Type *ret;
}func;
};
global Type global_type[] = {
{TYPE_Void},
{TYPE_Int, sizeof(int), __alignof(int)},
{TYPE_Char, sizeof(char), __alignof(char)},
};
const SizeU pointer_size = sizeof(SizeU);
const SizeU pointer_align = __alignof(SizeU);
global Type *type_void = global_type + 0;
global Type *type_int = global_type + 1;
global Type *type_char = global_type + 2;
global Map map_pointer_types;
global Map map_array_types;
global Map map_func_types;
function Type *
type_new(Arena *arena, Type_Kind kind, SizeU size, SizeU align){
Type *result = arena_push_struct(arena, Type);
result->kind = kind;
result->size = size;
result->align = align;
return result;
}
function Type *
type_copy(Arena *arena, Type *type){
Type *result = arena_push_struct(arena, Type);
memory_copy(result, type, sizeof(Type));
return result;
}
function Type *
type_incomplete(Arena *arena){
Type *result = type_new(arena, TYPE_Incomplete, 0, 0);
return result;
}
function Type *
type_pointer(Arena *arena, Type *base){
Type *result = map_get(&map_pointer_types, (void *)base);
if(!result){
result = type_new(arena, TYPE_Pointer, pointer_size, pointer_align);
result->pointer.base = base;
map_insert(&map_pointer_types, base, result);
}
return result;
}
function Type *
type_array(Arena *arena, Type *base, SizeU size){
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
Type *result = map_get_u64(&map_array_types, hash);
if(result){
assert(result->array.size == size);
assert(result->array.base == base);
return result;
}
result = type_new(arena, TYPE_Array, pointer_size, pointer_align);
result->array.base = base;
result->array.size = size;
map_insert_u64(&map_array_types, hash, result);
return result;
}
function Type *
type_lambda(Arena *arena, Type *ret, Type **params, S32 count){
U64 hash = hash_ptr(ret);
for(S32 i = 0; i < count; i++)
hash = hash_mix(hash, hash_ptr(params[i]));
Type *result = map_get_u64(&map_func_types, hash);
if(result){
assert(result->func.ret == ret);
assert(result->func.count == count);
return result;
}
result = type_new(arena, TYPE_Func, pointer_size, pointer_align);
result->func.ret = ret;
result->func.count = count;
result->func.params = arena_push_array(arena, Type*, count);
memory_copy(result->func.params, params, count);
map_insert_u64(&map_func_types, hash, result);
return result;
}
function void
test_types(){
Arena *arena = arena_begin_scratch();
Type *array_type1 = type_array(arena, type_int, 32);
Type *array_type2 = type_array(arena, type_int, 32);
Type *array_type3 = type_array(arena, type_int, 48);
assert(array_type1 == array_type2);
assert(array_type2 != array_type3);
Type *pointer_type1 = type_pointer(arena, type_int);
Type *pointer_type2 = type_pointer(arena, type_int);
assert(pointer_type2 == pointer_type1);
Type *pointer_type3 = type_pointer(arena, pointer_type1);
Type *pointer_type4 = type_pointer(arena, pointer_type2);
assert(pointer_type3 != pointer_type1);
assert(pointer_type3 == pointer_type4);
Type **types = 0;
array_push(types, type_array(arena, type_int, 32));
Type *func_type1 = type_lambda(arena, types[0], types, array_len(types));
Type *func_type2 = type_lambda(arena, types[0], types, array_len(types));
assert(func_type1 == func_type2);
Type **types2 = 0;
{
array_push(types2, type_array(arena, type_int, 32));
array_push(types2, type_int);
}
array_push(types, type_int);
Type *func_type3 = type_lambda(arena, types[0], types, array_len(types));
Type *func_type4 = type_lambda(arena, types[0], types2, array_len(types));
assert(func_type1 != func_type3);
assert(func_type3 == func_type4);
arena_end_scratch();
}