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;
}

84
lex.c
View File

@@ -27,7 +27,7 @@ function void
init_default_keywords(Intern_Table *t){ init_default_keywords(Intern_Table *t){
keyword_if = intern_string(t, lit("if")); keyword_if = intern_string(t, lit("if"));
first_keyword = keyword_if.s.str; first_keyword = keyword_if.s.str;
keyword_cast = intern_string(t, lit("cast")); keyword_cast = intern_string(t, lit("cast"));
keyword_for = intern_string(t, lit("for")); keyword_for = intern_string(t, lit("for"));
keyword_else = intern_string(t, lit("else")); keyword_else = intern_string(t, lit("else"));
@@ -44,16 +44,16 @@ init_default_keywords(Intern_Table *t){
keyword_case = intern_string(t, lit("case")); keyword_case = intern_string(t, lit("case"));
keyword_struct = intern_string(t, lit("struct")); keyword_struct = intern_string(t, lit("struct"));
keyword_enum = intern_string(t, lit("enum")); keyword_enum = intern_string(t, lit("enum"));
keyword_union = intern_string(t, lit("union")); keyword_union = intern_string(t, lit("union"));
last_keyword = keyword_union.s.str; last_keyword = keyword_union.s.str;
intern_char = intern_string(t, lit("char")); intern_char = intern_string(t, lit("char"));
intern_void = intern_string(t, lit("void")); intern_void = intern_string(t, lit("void"));
intern_int = intern_string(t, lit("int")); intern_int = intern_string(t, lit("int"));
} }
function B32 function B32
lex_is_keyword(Intern_String str){ lex_is_keyword(Intern_String str){
B32 result = str.s.str >= first_keyword && str.s.str <= last_keyword; B32 result = str.s.str >= first_keyword && str.s.str <= last_keyword;
return result; return result;
@@ -61,7 +61,7 @@ lex_is_keyword(Intern_String str){
typedef enum Token_Kind{ typedef enum Token_Kind{
TK_End, TK_End,
TK_Mul, TK_Mul,
TK_Div, TK_Div,
TK_Mod, TK_Mod,
@@ -69,12 +69,12 @@ typedef enum Token_Kind{
TK_RightShift, TK_RightShift,
TK_FirstMul = TK_Mul, TK_FirstMul = TK_Mul,
TK_LastMul = TK_RightShift, TK_LastMul = TK_RightShift,
TK_Add, TK_Add,
TK_Sub, TK_Sub,
TK_FirstAdd = TK_Add, TK_FirstAdd = TK_Add,
TK_LastAdd = TK_Sub, TK_LastAdd = TK_Sub,
TK_Equals, TK_Equals,
TK_LesserThenOrEqual, TK_LesserThenOrEqual,
TK_GreaterThenOrEqual, TK_GreaterThenOrEqual,
@@ -83,15 +83,15 @@ typedef enum Token_Kind{
TK_NotEquals, TK_NotEquals,
TK_FirstCompare = TK_Equals, TK_FirstCompare = TK_Equals,
TK_LastCompare = TK_NotEquals, TK_LastCompare = TK_NotEquals,
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,
TK_LastLogical = TK_Or, TK_LastLogical = TK_Or,
TK_Neg, TK_Neg,
TK_Not, TK_Not,
TK_OpenParen, TK_OpenParen,
@@ -106,9 +106,9 @@ typedef enum Token_Kind{
TK_ThreeDots, TK_ThreeDots,
TK_Semicolon, TK_Semicolon,
TK_Dot, TK_Dot,
TK_Colon, TK_Colon,
TK_Assign, TK_Assign,
TK_ColonAssign, TK_ColonAssign,
TK_DivAssign, TK_DivAssign,
@@ -123,14 +123,14 @@ typedef enum Token_Kind{
TK_RightShiftAssign, TK_RightShiftAssign,
TK_FirstAssign = TK_Assign, TK_FirstAssign = TK_Assign,
TK_LastAssign = TK_RightShiftAssign, TK_LastAssign = TK_RightShiftAssign,
TK_DoubleColon, TK_DoubleColon,
TK_At, TK_At,
TK_Decrement, TK_Decrement,
TK_Increment, TK_Increment,
TK_PostDecrement, TK_PostDecrement,
TK_PostIncrement, TK_PostIncrement,
TK_Arrow, TK_Arrow,
TK_ExprSizeof, TK_ExprSizeof,
TK_DocComment, TK_DocComment,
@@ -150,14 +150,14 @@ typedef struct Token{
String string; String string;
struct{U8 *str; S64 len;}; struct{U8 *str; S64 len;};
}; };
union { union {
U64 int_val; U64 int_val;
F64 float_val; F64 float_val;
String error_val; String error_val;
Intern_String intern_val; Intern_String intern_val;
}; };
String file; String file;
S32 line; S32 line;
U8 *line_begin; U8 *line_begin;
@@ -167,7 +167,7 @@ typedef struct Token{
typedef struct Lex_Stream{ typedef struct Lex_Stream{
String stream; String stream;
S64 iter; S64 iter;
U8 *line_begin; U8 *line_begin;
String file; String file;
S32 line; S32 line;
@@ -207,7 +207,7 @@ lex_is_numeric(U8 c){
return result; return result;
} }
function B32 function B32
lex_is_alphanumeric(U8 c){ lex_is_alphanumeric(U8 c){
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c); B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
return result; return result;
@@ -226,7 +226,7 @@ token_error(Token *t, String error_val){
} }
function void function void
lex_parse_u64(Token *t){ lex_parse_u64(Token *t){
U64 result = 0; U64 result = 0;
U64 m = 1; U64 m = 1;
for(S64 i = t->len - 1; i >= 0; --i){ for(S64 i = t->len - 1; i >= 0; --i){
@@ -257,7 +257,7 @@ lex_advance(Lex_Stream *s){
} }
} }
function void function void
lex_parse_string(Lex_Stream *s, Token *t, U8 c){ lex_parse_string(Lex_Stream *s, Token *t, U8 c){
for(;;){ for(;;){
if(lexc(s) == '\\') lex_advance(s); if(lexc(s) == '\\') lex_advance(s);
@@ -301,14 +301,14 @@ lex__stream(Token_Array *array, Lex_Stream *s){
while(lexc(s)){ while(lexc(s)){
while(lex_is_whitespace(lexc(s))) while(lex_is_whitespace(lexc(s)))
lex_advance(s); lex_advance(s);
Token t = {0}; Token t = {0};
t.str = lexcp(s); t.str = lexcp(s);
t.file = s->file; t.file = s->file;
t.line = s->line; t.line = s->line;
t.line_begin = s->line_begin; t.line_begin = s->line_begin;
lex_advance(s); lex_advance(s);
switch(*t.str){ switch(*t.str){
case 0: break; case 0: break;
case '@': t.kind = TK_At; break; case '@': t.kind = TK_At; break;
@@ -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);
@@ -342,8 +342,8 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_Dot; t.kind = TK_Dot;
} }
} break; } break;
case '<': { case '<': {
if (lexc(s) == '<') { if (lexc(s) == '<') {
lex_advance(s); lex_advance(s);
@@ -363,7 +363,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_LesserThen; t.kind = TK_LesserThen;
} }
} break; } break;
case '>': { case '>': {
if (lexc(s) == '>') { if (lexc(s) == '>') {
lex_advance(s); lex_advance(s);
@@ -383,7 +383,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_GreaterThen; t.kind = TK_GreaterThen;
} }
} break; } break;
case ':': { case ':': {
if (lexc(s) == ':') { if (lexc(s) == ':') {
lex_advance(s); lex_advance(s);
@@ -397,7 +397,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_Colon; t.kind = TK_Colon;
} }
} break; } break;
case '-':{ case '-':{
if (lexc(s) == '=') { if (lexc(s) == '=') {
lex_advance(s); lex_advance(s);
@@ -415,11 +415,11 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_Sub; t.kind = TK_Sub;
} }
} break; } break;
case '\'':{not_implemented;} break; case '\'':{not_implemented;} break;
case '"': { case '"': {
t.kind = TK_StringLit; t.kind = TK_StringLit;
lex_parse_string(s,&t,'"'); lex_parse_string(s,&t,'"');
if(t.kind != TK_Error){ if(t.kind != TK_Error){
t.str += 1; t.str += 1;
@@ -427,7 +427,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
} }
t.intern_val = intern_string(&array->interns, t.string); t.intern_val = intern_string(&array->interns, t.string);
} break; } break;
case '/': { case '/': {
if(lexc(s) == '='){ if(lexc(s) == '='){
t.kind = TK_DivAssign; t.kind = TK_DivAssign;
@@ -464,7 +464,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_Div; t.kind = TK_Div;
} }
} break; } break;
case '0':case '1':case '2':case '3':case '4': case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':{ case '5':case '6':case '7':case '8':case '9':{
t.kind = TK_Integer; t.kind = TK_Integer;
@@ -473,7 +473,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
lex_set_len(s, &t); lex_set_len(s, &t);
lex_parse_u64(&t); lex_parse_u64(&t);
} break; } break;
case 'A':case 'a':case 'M':case 'm':case 'B': case 'A':case 'a':case 'M':case 'm':case 'B':
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O': case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
case 'o':case 'D':case 'd':case 'P':case 'p':case 'E': case 'o':case 'D':case 'd':case 'P':case 'p':case 'E':
@@ -492,15 +492,15 @@ lex__stream(Token_Array *array, Lex_Stream *s){
t.kind = TK_Keyword; t.kind = TK_Keyword;
} }
} break; } break;
default: { default: {
token_error(&t, lit("Unknown token")); token_error(&t, lit("Unknown token"));
} }
} }
if(t.len==0) if(t.len==0)
lex_set_len(s,&t); lex_set_len(s,&t);
token_array_push(array, &t); token_array_push(array, &t);
} }
} }
@@ -538,13 +538,13 @@ lex_test(){
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615" "\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
"for if while switch :="); "for if while switch :=");
Token_Array array = lex_stream(scratch, test, lit("Test1")); Token_Array array = lex_stream(scratch, test, lit("Test1"));
Token_Kind kind[] = { Token_Kind kind[] = {
TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen, TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon, TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon,
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon, TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign, TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
TK_Equals, TK_Integer, TK_Integer, TK_Integer, TK_Keyword, TK_Keyword, TK_Equals, TK_Integer, TK_Integer, TK_Integer, TK_Keyword, TK_Keyword,
TK_Keyword, TK_Keyword, TK_ColonAssign, TK_End TK_Keyword, TK_Keyword, TK_ColonAssign, TK_End
}; };
String strs[] = { String strs[] = {
@@ -558,7 +558,7 @@ lex_test(){
U64 vals[] = { U64 vals[] = {
42524, 4294967295, 18446744073709551615llu 42524, 4294967295, 18446744073709551615llu
}; };
int i = 0; int i = 0;
int ui = 0; int ui = 0;
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){ for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
@@ -569,7 +569,7 @@ lex_test(){
} }
} }
arena_end_scratch(); arena_end_scratch();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -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,21 +5,20 @@
#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();
test_parse_expr(); test_parse_expr();
map_test(); map_test();
test_array(); test_array();
test_string_builder(); test_string_builder();
test_intern_table(); test_intern_table();
lex_test(); lex_test();
} }

View File

@@ -4,7 +4,7 @@
// //
// Parser::ast_arena - arena for asts // Parser::ast_arena - arena for asts
// Lexer::interns::string_allocator - arena for interns // Lexer::interns::string_allocator - arena for interns
// //
Intern_String keyword_struct; Intern_String keyword_struct;
Intern_String keyword_union; Intern_String keyword_union;
Intern_String keyword_cast; Intern_String keyword_cast;
@@ -19,21 +19,25 @@ const U64 Parse_Ctx_ID = 115151;
struct Parse_Ctx:Lexer{ struct Parse_Ctx:Lexer{
Allocator *perm; // Stores: AST, tokens, interns Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap; Allocator *heap;
U64 unique_ids; 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;
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;
global_syms = {heap}; global_syms = {heap};
type_map = {heap}; type_map = {heap};
lex_init(perm, heap, this); lex_init(perm, heap, this);
keyword_struct= intern_string(&interns, "struct"_s); keyword_struct= intern_string(&interns, "struct"_s);
keyword_union = intern_string(&interns, "union"_s); keyword_union = intern_string(&interns, "union"_s);
@@ -41,7 +45,7 @@ struct Parse_Ctx:Lexer{
keyword_enum = intern_string(&interns, "enum"_s); keyword_enum = intern_string(&interns, "enum"_s);
interns.first_keyword = keyword_struct.str; interns.first_keyword = keyword_struct.str;
interns.last_keyword = keyword_enum.str; interns.last_keyword = keyword_enum.str;
intern_void = intern_string(&interns, "void"_s); intern_void = intern_string(&interns, "void"_s);
intern_int = intern_string(&interns, "int"_s); intern_int = intern_string(&interns, "int"_s);
intern_str = intern_string(&interns, "String"_s); intern_str = intern_string(&interns, "String"_s);
@@ -55,9 +59,9 @@ thread_local Parse_Ctx *pctx;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
enum Ast_Kind{ enum Ast_Kind{
AST_NONE, AST_NONE,
AST_PACKAGE, AST_PACKAGE,
AST_STR, AST_STR,
AST_INT, AST_INT,
AST_CAST, AST_CAST,
@@ -67,12 +71,12 @@ enum Ast_Kind{
AST_BINARY, AST_BINARY,
AST_COMPOUND_ITEM, AST_COMPOUND_ITEM,
AST_COMPOUND, AST_COMPOUND,
AST_LAMBDA, AST_LAMBDA,
AST_LAMBDA_PARAM, AST_LAMBDA_PARAM,
AST_CONST, AST_CONST,
AST_VAR, AST_VAR,
AST_TYPESPEC_IDENT, AST_TYPESPEC_IDENT,
AST_TYPESPEC_POINTER, AST_TYPESPEC_POINTER,
AST_TYPESPEC_ARRAY, AST_TYPESPEC_ARRAY,
@@ -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){
@@ -327,4 +335,4 @@ ast_package(Token *pos, String name, Array<Ast_Decl *> decls){
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

@@ -1,7 +1,7 @@
enum Token_Kind{ enum Token_Kind{
TK_End, TK_End,
TK_Mul, TK_Mul,
TK_Div, TK_Div,
TK_Mod, TK_Mod,
@@ -9,12 +9,12 @@ enum Token_Kind{
TK_RightShift, TK_RightShift,
TK_FirstMul = TK_Mul, TK_FirstMul = TK_Mul,
TK_LastMul = TK_RightShift, TK_LastMul = TK_RightShift,
TK_Add, TK_Add,
TK_Sub, TK_Sub,
TK_FirstAdd = TK_Add, TK_FirstAdd = TK_Add,
TK_LastAdd = TK_Sub, TK_LastAdd = TK_Sub,
TK_Equals, TK_Equals,
TK_LesserThenOrEqual, TK_LesserThenOrEqual,
TK_GreaterThenOrEqual, TK_GreaterThenOrEqual,
@@ -23,15 +23,14 @@ enum Token_Kind{
TK_NotEquals, TK_NotEquals,
TK_FirstCompare = TK_Equals, TK_FirstCompare = TK_Equals,
TK_LastCompare = TK_NotEquals, TK_LastCompare = TK_NotEquals,
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,
TK_LastLogical = TK_Or, TK_LastLogical = TK_Or,
TK_Neg, TK_Neg,
TK_Not, TK_Not,
TK_OpenParen, TK_OpenParen,
@@ -46,10 +45,10 @@ enum Token_Kind{
TK_ThreeDots, TK_ThreeDots,
TK_Semicolon, TK_Semicolon,
TK_Dot, TK_Dot,
TK_NewLine, TK_NewLine,
TK_Colon, TK_Colon,
TK_Assign, TK_Assign,
TK_DivAssign, TK_DivAssign,
TK_MulAssign, TK_MulAssign,
@@ -63,14 +62,14 @@ enum Token_Kind{
TK_RightShiftAssign, TK_RightShiftAssign,
TK_FirstAssign = TK_Assign, TK_FirstAssign = TK_Assign,
TK_LastAssign = TK_RightShiftAssign, TK_LastAssign = TK_RightShiftAssign,
TK_DoubleColon, TK_DoubleColon,
TK_At, TK_At,
TK_Decrement, TK_Decrement,
TK_Increment, TK_Increment,
TK_PostDecrement, TK_PostDecrement,
TK_PostIncrement, TK_PostIncrement,
TK_Arrow, TK_Arrow,
TK_ExprSizeof, TK_ExprSizeof,
TK_DocComment, TK_DocComment,
@@ -82,8 +81,8 @@ enum Token_Kind{
TK_Float, TK_Float,
TK_Integer, TK_Integer,
TK_Keyword, TK_Keyword,
TK_Pointer = TK_BitXor, TK_Pointer,
TK_Dereference, TK_Dereference,
}; };
@@ -93,7 +92,7 @@ struct Token{
String string; String string;
struct{U8 *str; S64 len;}; struct{U8 *str; S64 len;};
}; };
union { union {
U64 int_val; U64 int_val;
F64 float_val; F64 float_val;
@@ -101,7 +100,7 @@ struct Token{
Intern_String intern_val; Intern_String intern_val;
S64 indent; S64 indent;
}; };
String file; String file;
S32 line; S32 line;
U8 *line_begin; U8 *line_begin;
@@ -110,7 +109,7 @@ struct Token{
struct Lex_Stream{ struct Lex_Stream{
String stream; String stream;
S64 iter; S64 iter;
U8 *line_begin; U8 *line_begin;
String file; String file;
S32 line; S32 line;
@@ -157,7 +156,7 @@ lex_is_numeric(U8 c){
return result; return result;
} }
function B32 function B32
lex_is_alphanumeric(U8 c){ lex_is_alphanumeric(U8 c){
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c); B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
return result; return result;
@@ -172,9 +171,9 @@ 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;
} }
lexer->interns.last_keyword = keyword.str; lexer->interns.last_keyword = keyword.str;
@@ -193,7 +192,7 @@ token_error(Token *t, String error_val){
} }
function void function void
lex_parse_u64(Token *t){ lex_parse_u64(Token *t){
U64 result = 0; U64 result = 0;
U64 m = 1; U64 m = 1;
for(S64 i = t->len - 1; i >= 0; --i){ for(S64 i = t->len - 1; i >= 0; --i){
@@ -224,7 +223,7 @@ lex_advance(Lex_Stream *s){
} }
} }
function void function void
lex_parse_string(Lex_Stream *s, Token *t, U8 c){ lex_parse_string(Lex_Stream *s, Token *t, U8 c){
for(;;){ for(;;){
if(lexc(s) == '\\') lex_advance(s); if(lexc(s) == '\\') lex_advance(s);
@@ -241,39 +240,39 @@ 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){
while(lexc(s)){ while(lexc(s)){
Token t = {}; Token t = {};
t.str = lexcp(s); t.str = lexcp(s);
t.file = s->file; t.file = s->file;
t.line = s->line; t.line = s->line;
t.line_begin = s->line_begin; t.line_begin = s->line_begin;
lex_advance(s); lex_advance(s);
switch(*t.str){ switch(*t.str){
case 0 : break; case 0 : break;
case '@': t.kind = TK_At; break; case '@': t.kind = TK_At; break;
@@ -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);
@@ -298,15 +297,15 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
#undef CASE2 #undef CASE2
#undef CASE3 #undef CASE3
case ';': { case ';': {
t.kind = TK_Semicolon; t.kind = TK_Semicolon;
}break; }break;
case ' ' : s->stream.str -= 1; case ' ' : s->stream.str -= 1;
case '\n': { case '\n': {
t.kind = TK_NewLine; t.kind = TK_NewLine;
if(lexc(s) == '\r') if(lexc(s) == '\r')
lex_advance(s); lex_advance(s);
for(;;){ for(;;){
if(lexc(s) == ' ') { if(lexc(s) == ' ') {
t.indent++; t.indent++;
@@ -316,7 +315,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
else break; else break;
lex_advance(s); lex_advance(s);
} }
}break; }break;
case '.': { case '.': {
if(lexc(s) == '.' && lexci(s,1) == '.') { if(lexc(s) == '.' && lexci(s,1) == '.') {
@@ -327,8 +326,8 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_Dot; t.kind = TK_Dot;
} }
} break; } break;
case '<': { case '<': {
if (lexc(s) == '<') { if (lexc(s) == '<') {
lex_advance(s); lex_advance(s);
@@ -348,7 +347,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_LesserThen; t.kind = TK_LesserThen;
} }
} break; } break;
case '>': { case '>': {
if (lexc(s) == '>') { if (lexc(s) == '>') {
lex_advance(s); lex_advance(s);
@@ -368,7 +367,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_GreaterThen; t.kind = TK_GreaterThen;
} }
} break; } break;
case ':': { case ':': {
if (lexc(s) == ':') { if (lexc(s) == ':') {
lex_advance(s); lex_advance(s);
@@ -378,7 +377,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_Colon; t.kind = TK_Colon;
} }
} break; } break;
case '-':{ case '-':{
if (lexc(s) == '=') { if (lexc(s) == '=') {
lex_advance(s); lex_advance(s);
@@ -396,11 +395,11 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_Sub; t.kind = TK_Sub;
} }
} break; } break;
case '\'':{not_implemented;} break; case '\'':{not_implemented;} break;
case '"': { case '"': {
t.kind = TK_StringLit; t.kind = TK_StringLit;
lex_parse_string(s,&t,'"'); lex_parse_string(s,&t,'"');
if(t.kind != TK_Error){ if(t.kind != TK_Error){
t.str += 1; t.str += 1;
@@ -408,7 +407,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
} }
t.intern_val = intern_string(table, t.string); t.intern_val = intern_string(table, t.string);
} break; } break;
case '/': { case '/': {
if(lexc(s) == '='){ if(lexc(s) == '='){
t.kind = TK_DivAssign; t.kind = TK_DivAssign;
@@ -445,7 +444,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_Div; t.kind = TK_Div;
} }
} break; } break;
case '0':case '1':case '2':case '3':case '4': case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':{ case '5':case '6':case '7':case '8':case '9':{
t.kind = TK_Integer; t.kind = TK_Integer;
@@ -454,7 +453,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
lex_set_len(s, &t); lex_set_len(s, &t);
lex_parse_u64(&t); lex_parse_u64(&t);
} break; } break;
case 'A':case 'a':case 'M':case 'm':case 'B': case 'A':case 'a':case 'M':case 'm':case 'B':
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O': case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
case 'o':case 'D':case 'd':case 'P':case 'p':case 'E': case 'o':case 'D':case 'd':case 'P':case 'p':case 'E':
@@ -473,23 +472,23 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
t.kind = TK_Keyword; t.kind = TK_Keyword;
} }
} break; } break;
default: { default: {
token_error(&t, "Unknown token"_s); token_error(&t, "Unknown token"_s);
} }
} }
if(t.len==0) if(t.len==0)
lex_set_len(s,&t); lex_set_len(s,&t);
B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0; B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0;
if(!skip){ if(!skip){
array->add(t); array->add(t);
} }
while(lex_is_whitespace(lexc(s))) while(lex_is_whitespace(lexc(s)))
lex_advance(s); lex_advance(s);
if(s->iter >= s->stream.len) // End of stream if(s->iter >= s->stream.len) // End of stream
break; break;
} }
@@ -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);
@@ -529,26 +533,26 @@ lex_test(){
String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\" Thingy" String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\" Thingy"
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615" "\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
"for if while switch :="_s; "for if while switch :="_s;
Array<String> keywords = {scratch}; Array<String> keywords = {scratch};
keywords.add("Keyword"_s); keywords.add("Keyword"_s);
keywords.add("for"_s); keywords.add("for"_s);
keywords.add("if"_s); keywords.add("if"_s);
keywords.add("while"_s); keywords.add("while"_s);
keywords.add("switch"_s); keywords.add("switch"_s);
Lexer lexer = lex_make(scratch, scratch); Lexer lexer = lex_make(scratch, scratch);
lex_set_keywords(&lexer, keywords); lex_set_keywords(&lexer, keywords);
lex_restream(&lexer, test, "Test1"_s); lex_restream(&lexer, test, "Test1"_s);
Array<Token> arr = lexer.tokens; Array<Token> arr = lexer.tokens;
Token_Kind kind[] = { Token_Kind kind[] = {
TK_Keyword, TK_NewLine, TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen, TK_Keyword, TK_NewLine, TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon, TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon,
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon, TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign, TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
TK_Equals, TK_Integer, TK_Integer, TK_Integer, TK_Equals, TK_Integer, TK_Integer, TK_Integer,
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
TK_Colon, TK_Assign, TK_End TK_Colon, TK_Assign, TK_End
}; };
String strs[] = { String strs[] = {
@@ -562,7 +566,7 @@ lex_test(){
U64 vals[] = { U64 vals[] = {
42524, 4294967295, 18446744073709551615llu 42524, 4294967295, 18446744073709551615llu
}; };
int ui = 0; int ui = 0;
For(arr){ For(arr){
assert(it->kind == kind[i]); assert(it->kind == kind[i]);
@@ -576,7 +580,7 @@ lex_test(){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Token metadata // Token metadata
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function String function String
token_kind_string(Token_Kind kind){ token_kind_string(Token_Kind kind){
switch(kind){ switch(kind){
case TK_End: return "End of stream"_s; case TK_End: return "End of stream"_s;
@@ -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

@@ -9,12 +9,12 @@ token_get(S64 i = 0){
if(result->kind == TK_NewLine){ if(result->kind == TK_NewLine){
pctx->indent = result->indent; pctx->indent = result->indent;
} }
return result; return result;
} }
function Token * function Token *
token_next(){ token_next(){
Token *token = token_get(); Token *token = token_get();
pctx->token_iter++; pctx->token_iter++;
return token; return token;
@@ -51,28 +51,28 @@ token_match_keyword(Intern_String string){
} }
function void function void
parsing_error(Token *token, const char *str, ...){ parsing_error(Token *token, const char *str, ...){
Scratch scratch; Scratch scratch;
STRING_FMT(scratch, str, string); STRING_FMT(scratch, str, string);
// @Note(Krzosa): Print nice error message // @Note(Krzosa): Print nice error message
printf("\nError: %s", string.str); printf("\nError: %s", string.str);
if(token){ if(token){
printf(" %s:%d\n", token->file.str, (S32)token->line); printf(" %s:%d\n", token->file.str, (S32)token->line);
// @Note(Krzosa): Print error line // @Note(Krzosa): Print error line
{ {
int i = 0; int i = 0;
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
printf("%.*s\n", i, token->line_begin); printf("%.*s\n", i, token->line_begin);
// @Note(Krzosa): Print error marker // @Note(Krzosa): Print error marker
int token_i = token->str - token->line_begin; int token_i = token->str - token->line_begin;
for(int i = 0; i < token_i-2; i++) printf(" "); for(int i = 0; i < token_i-2; i++) printf(" ");
printf("^^^^^^\n"); printf("^^^^^^\n");
} }
} }
__debugbreak(); __debugbreak();
} }
@@ -97,15 +97,15 @@ compare = == | != | >= | > | <= | <
logical = [&|^] | && | || logical = [&|^] | && | ||
unary = [&*-!~+] | ++ | -- unary = [&*-!~+] | ++ | --
atom_expr = Int atom_expr = Int
| Float | Float
| String | String
| Identifier | Identifier
| 'cast' '(' typespec ',' expr ')' | 'cast' '(' typespec ',' expr ')'
| 'size_type' '(' typespec ')' | 'size_type' '(' typespec ')'
| 'size_expr' '(' expr ')' | 'size_expr' '(' expr ')'
| '{' compound_expr '}' | '{' compound_expr '}'
| '(' expr ')' | '(' expr ')'
| '(' ':' typespec ')' '{' compound_expr '}' | '(' ':' typespec ')' '{' compound_expr '}'
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
unary_expr = unary ? unary_expr : atom_expr unary_expr = unary ? unary_expr : atom_expr
@@ -143,17 +143,17 @@ parse_expr_compound(){
name = ast_expr_identifier(token, token->intern_val); name = ast_expr_identifier(token, token->intern_val);
token_expect(TK_Assign); token_expect(TK_Assign);
} }
Ast_Expr *item = parse_expr(); Ast_Expr *item = parse_expr();
Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item); Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item);
exprs.add(item_comp); exprs.add(item_comp);
if(!token_match(TK_Comma)){ if(!token_match(TK_Comma)){
break; break;
} }
} }
token_expect(TK_CloseBrace); token_expect(TK_CloseBrace);
Ast_Expr *result = ast_expr_compound(pos, 0, exprs); Ast_Expr *result = ast_expr_compound(pos, 0, exprs);
return result; return result;
} }
@@ -165,14 +165,24 @@ 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 "()"
// We needed to lookahead to verify it's a function // We needed to lookahead to verify it's a function
// and this routine only fires when we have situation // and this routine only fires when we have situation
// with at least one parameter // with at least one parameter
for(;;){ for(;;){
Token *name = token_expect(TK_Identifier); Token *name = token_expect(TK_Identifier);
@@ -180,12 +190,14 @@ parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typesp
Ast_Typespec *typespec = parse_typespec(); Ast_Typespec *typespec = parse_typespec();
Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec); Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec);
params.add(param); params.add(param);
if(!token_match(TK_Comma)){ if(!token_match(TK_Comma)){
break; break;
} }
} }
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);
@@ -207,7 +219,7 @@ null_denotation(Token *token){
return ast_expr_cast(token, expr, typespec); return ast_expr_cast(token, expr, typespec);
} }
else { else {
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str); parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
return 0; return 0;
} }
}break; }break;
@@ -216,8 +228,8 @@ null_denotation(Token *token){
if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token); 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 if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token);
else{ else{
Ast_Expr *result = parse_expr(); Ast_Expr *result = parse_expr();
token_expect(TK_CloseParen); token_expect(TK_CloseParen);
return result; return result;
} }
} }
@@ -226,18 +238,18 @@ null_denotation(Token *token){
} }
function S64 function S64
left_binding_power(Token_Kind kind){ left_binding_power(Token_Kind kind){
switch(kind){ switch(kind){
case TK_Sub: case TK_Add: return 1; case TK_Sub: case TK_Add: return 1;
case TK_Mul: case TK_Div: return 2; case TK_Mul: case TK_Div: return 2;
default: return 0; default: return 0;
} }
} }
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;
} }
} }
@@ -259,11 +271,11 @@ parse_expr(S64 rbp){
Ast_Expr *left = null_denotation(token); Ast_Expr *left = null_denotation(token);
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();
left = ast_expr_index(token, left, index); left = ast_expr_index(token, left, index);
token_expect(TK_CloseBracket); token_expect(TK_CloseBracket);
} }
@@ -273,13 +285,13 @@ parse_expr(S64 rbp){
left = ast_expr_unary(token, token->kind, left); left = ast_expr_unary(token, token->kind, left);
} }
} }
else if(rbp < left_binding_power(token->kind)){ else if(rbp < left_binding_power(token->kind)){
token = token_next(); token = token_next();
left = left_denotation(token, left); left = left_denotation(token, left);
} }
else break; else break;
} }
return left; return left;
} }
@@ -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(){
@@ -329,8 +341,8 @@ test_parse_expr(){
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});
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;
@@ -395,20 +406,20 @@ parse_decl(){
Ast_Expr *expr = parse_expr(); Ast_Expr *expr = parse_expr();
result = ast_decl_const(name, name->intern_val, expr); result = ast_decl_const(name, name->intern_val, expr);
} }
else if(token_match(TK_Colon)){ else if(token_match(TK_Colon)){
Ast_Typespec *typespec = 0; Ast_Typespec *typespec = 0;
Ast_Expr *expr = 0; Ast_Expr *expr = 0;
if(!token_is(TK_Assign)) typespec = parse_typespec(); if(!token_is(TK_Assign)) typespec = parse_typespec();
if(token_match(TK_Assign)) expr = parse_expr(); if(token_match(TK_Assign)) expr = parse_expr();
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value"); if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
result = ast_decl_var(name, typespec, name->intern_val, expr); result = ast_decl_var(name, typespec, name->intern_val, expr);
} }
else{ else{
Token *token = token_get(); Token *token = token_get();
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str); parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
} }
} }
return result; return result;
} }

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{
@@ -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;
@@ -33,9 +33,9 @@ sym_insert(Sym *sym){
U64 hash = hash_string(sym->name.s); U64 hash = hash_string(sym->name.s);
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash); Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
if(is_sym){ if(is_sym){
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
} }
map_insert_u64(&pctx->global_syms, hash, sym); map_insert_u64(&pctx->global_syms, hash, sym);
} }
@@ -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);
@@ -69,33 +69,31 @@ sym_insert_builtins(){
sym_insert_builtin_type("bool"_s, type_bool); sym_insert_builtin_type("bool"_s, type_bool);
sym_insert_builtin_type("int"_s, type_int); sym_insert_builtin_type("int"_s, type_int);
sym_insert_builtin_type("String"_s, type_string); sym_insert_builtin_type("String"_s, type_string);
{ {
Intern_String string = intern_string(&pctx->interns, "true"_s); Intern_String string = intern_string(&pctx->interns, "true"_s);
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl); Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
sym_insert(sym); sym_insert(sym);
} }
{ {
Intern_String string = intern_string(&pctx->interns, "false"_s); Intern_String string = intern_string(&pctx->interns, "false"_s);
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl); Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
sym_insert(sym); sym_insert(sym);
} }
{ {
Intern_String string = intern_string(&pctx->interns, "null"_s); Intern_String string = intern_string(&pctx->interns, "null"_s);
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;
switch(ast->kind){ switch(ast->kind){
Ast_Begin(AST_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);
@@ -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,43 +140,94 @@ 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}};
return result; return result;
Ast_End(); Ast_End();
} }
Ast_Begin(AST_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(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();
} }
Ast_Begin(AST_INDEX, Ast_Expr){ Ast_Begin(AST_INDEX, Ast_Expr){
Operand left = eval_expr(node->index.expr); Operand left = eval_expr(node->index.expr);
Operand index = eval_expr(node->index.index); Operand index = eval_expr(node->index.index);
@@ -186,81 +237,71 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
return result; return result;
Ast_End(); Ast_End();
} }
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);
} }
} }
else parsing_error(node->pos, "Invalid compound expression type"); else parsing_error(node->pos, "Invalid compound expression type");
Operand result = {type, false}; Operand result = {type, false};
return result; return result;
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;
else if(expr.type == type_int && type == type_bool){ else if(expr.type == type_int && type == type_bool){
expr.type = type_bool; expr.type = type_bool;
return expr; return expr;
} }
else if(expr.type == type_bool && type == type_int){ else if(expr.type == type_bool && type == type_int){
expr.type = type_int; expr.type = type_int;
return expr; return expr;
} }
else if(expr.type == type_null){ else if(expr.type == type_null){
expr.type = type; expr.type = type;
return expr; return expr;
} }
else parsing_error(node->pos, "Failed to cast, incompatible types"); else parsing_error(node->pos, "Failed to cast, incompatible types");
Ast_End(); Ast_End();
} }
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;
@@ -271,10 +312,10 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
}break; }break;
invalid_default_case; return {}; invalid_default_case; return {};
} }
Ast_End(); Ast_End();
} }
Ast_Begin(AST_BINARY, Ast_Expr){ 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);
@@ -293,51 +334,51 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
} }
else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported"); else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported");
} }
return result; return result;
Ast_End(); Ast_End();
} }
invalid_default_case; invalid_default_case;
} }
return {}; return {};
} }
function void function void
eval_decl(Ast *ast){ eval_decl(Ast *ast){
switch(ast->kind){ switch(ast->kind){
Ast_Begin(AST_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(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);
Ast_End(); Ast_End();
} }
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;
else if(resolved_type == type_string) sym->intern_val = expr.intern_val; else if(resolved_type == type_string) sym->intern_val = expr.intern_val;
sym_insert(sym); sym_insert(sym);
Ast_End(); Ast_End();
} }
invalid_default_case; invalid_default_case;
} }
} }

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,17 +92,17 @@ 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);
assert(result->arr.base == base); assert(result->arr.base == base);
return result; return result;
} }
result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align);
result->arr.base = base; result->arr.base = base;
result->arr.size = size; result->arr.size = size;
@@ -110,24 +110,24 @@ 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);
return result; return result;
} }
@@ -137,34 +137,34 @@ test_types(){
Parse_Ctx ctx = {}; Parse_Ctx ctx = {};
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;
};

74
parse.c
View File

@@ -9,7 +9,7 @@ struct Parser_Error{
typedef struct Parser{ typedef struct Parser{
Token_Array tokens; Token_Array tokens;
Arena *arena; Arena *arena;
Parser_Error *first_error; Parser_Error *first_error;
Parser_Error *last_error; Parser_Error *last_error;
}Parser; }Parser;
@@ -38,36 +38,36 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
va_copy(args2, args1); va_copy(args2, args1);
string.len = vsnprintf(0, 0, str, args2); string.len = vsnprintf(0, 0, str, args2);
va_end(args2); va_end(args2);
string.str = arena_push_size(p->arena, string.len + 1); string.str = arena_push_size(p->arena, string.len + 1);
vsnprintf((char*)string.str, string.len + 1, str, args1); vsnprintf((char*)string.str, string.len + 1, str, args1);
va_end(args1); va_end(args1);
} }
// @Note(Krzosa): Print nice error message // @Note(Krzosa): Print nice error message
printf("\nError: %s", string.str); printf("\nError: %s", string.str);
if(token){ if(token){
printf(" %s:%d\n", token->file.str, (S32)token->line); printf(" %s:%d\n", token->file.str, (S32)token->line);
// @Note(Krzosa): Print error line // @Note(Krzosa): Print error line
{ {
int i = 0; int i = 0;
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
printf("%.*s\n", i, token->line_begin); printf("%.*s\n", i, token->line_begin);
// @Note(Krzosa): Print error marker // @Note(Krzosa): Print error marker
int token_i = token->str - token->line_begin; int token_i = token->str - token->line_begin;
for(int i = 0; i < token_i-2; i++) printf(" "); for(int i = 0; i < token_i-2; i++) printf(" ");
printf("^^^^^^\n"); printf("^^^^^^\n");
} }
} }
Parser_Error *error = arena_push_struct(p->arena, Parser_Error); Parser_Error *error = arena_push_struct(p->arena, Parser_Error);
error->message = string; error->message = string;
error->next = 0; error->next = 0;
error->token = token; error->token = token;
SLLQueuePush(p->first_error, p->last_error, error); SLLQueuePush(p->first_error, p->last_error, error);
__debugbreak(); __debugbreak();
} }
@@ -162,15 +162,15 @@ compare = == | != | >= | > | <= | <
logical = [&|^] | && | || logical = [&|^] | && | ||
unary = [&*-!~+] | ++ | -- unary = [&*-!~+] | ++ | --
atom_expr = Int atom_expr = Int
| Float | Float
| String | String
| Identifier | Identifier
| 'cast' '(' typespec ',' expr ')' | 'cast' '(' typespec ',' expr ')'
| 'size_type' '(' typespec ')' | 'size_type' '(' typespec ')'
| 'size_expr' '(' expr ')' | 'size_expr' '(' expr ')'
| '{' compound_expr '}' | '{' compound_expr '}'
| '(' expr ')' | '(' expr ')'
| '(' ':' typespec ')' '{' compound_expr '}' | '(' ':' typespec ')' '{' compound_expr '}'
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
unary_expr = unary ? unary_expr : atom_expr unary_expr = unary ? unary_expr : atom_expr
@@ -205,7 +205,7 @@ parse_expr_compound_field(Parser *p){
parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value"); parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value");
} }
result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p)); result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p));
} }
else{ else{
result = expr_compound_default(p->arena, token, expr); result = expr_compound_default(p->arena, token, expr);
@@ -251,7 +251,7 @@ parse_expr_atom(Parser *p){
else if(token_is(p, TK_OpenBrace)){ else if(token_is(p, TK_OpenBrace)){
result = parse_expr_compound(p, 0); result = parse_expr_compound(p, 0);
} }
else if(token_match(p, TK_OpenParen)){ else if(token_match(p, TK_OpenParen)){
if(token_match(p, TK_Colon)){ if(token_match(p, TK_Colon)){
Typespec *typespec = parse_typespec(p); Typespec *typespec = parse_typespec(p);
@@ -343,7 +343,7 @@ parse_expr_postfix(Parser *p){
function B32 function B32
token_is_unary(Parser *p){ token_is_unary(Parser *p){
Token *token = token_get(p); Token *token = token_get(p);
B32 result = token->kind == TK_Add B32 result = token->kind == TK_Add
|| token->kind == TK_Increment || token->kind == TK_Increment
|| token->kind == TK_Decrement || token->kind == TK_Decrement
|| token->kind == TK_Sub || token->kind == TK_Sub
@@ -462,15 +462,15 @@ parse_expr(Parser *p){
// Type specifier parsing // Type specifier parsing
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/* /*
base_type = NAME base_type = NAME
| '(' type_list? ')' type? | '(' type_list? ')' type?
type = ('*' | '[' expr ']')* base_type type = ('*' | '[' expr ']')* base_type
Examples: Examples:
[32]*U32 - Array of 32 pointers to U32 [32]*U32 - Array of 32 pointers to U32
**CustomDataType - Pointer to pointer of CustomDataType **CustomDataType - Pointer to pointer of CustomDataType
(*U32, S64) **S64 - Function pointer (*U32, S64) **S64 - Function pointer
(CoolType: optional, S32) - Implicit void return value (CoolType: optional, S32) - Implicit void return value
*/ */
@@ -490,9 +490,9 @@ parse_optional_type(Parser *p, Intern_String type){
function Typespec * function Typespec *
parse_typespec_function(Parser *p, Token *token){ parse_typespec_function(Parser *p, Token *token){
Typespec *result = typespec_function(p->arena, token, 0); Typespec *result = typespec_function(p->arena, token, 0);
if(!token_is(p, TK_CloseParen)) if(!token_is(p, TK_CloseParen))
for(;;) { for(;;) {
// Optional name // Optional name
Token *name = 0; Token *name = 0;
if((token = token_is(p, TK_Identifier))){ if((token = token_is(p, TK_Identifier))){
@@ -502,21 +502,21 @@ parse_typespec_function(Parser *p, Token *token){
name = token; name = token;
} }
} }
// Parse type // Parse type
Typespec *arg = parse_typespec(p); Typespec *arg = parse_typespec(p);
if(name) if(name)
arg = typespec_named_argument(p->arena, name, arg, name->intern_val); arg = typespec_named_argument(p->arena, name, arg, name->intern_val);
typespec_function_push(result, arg); typespec_function_push(result, arg);
if(!token_match(p, TK_Comma)){ if(!token_match(p, TK_Comma)){
break; break;
} }
} }
token_expect(p, TK_CloseParen); token_expect(p, TK_CloseParen);
result->func.ret = parse_optional_type(p, intern_void); result->func.ret = parse_optional_type(p, intern_void);
return result; return result;
} }
@@ -578,7 +578,7 @@ name::const = 4254;
// } // }
// } // }
*/ */
function void function void
parse_note_list(Parser *p, AST_Parent *parent) { parse_note_list(Parser *p, AST_Parent *parent) {
if(token_match(p, TK_OpenParen)) { if(token_match(p, TK_OpenParen)) {
if(token_match(p, TK_CloseParen)){ if(token_match(p, TK_CloseParen)){
@@ -596,7 +596,7 @@ parse_note_list(Parser *p, AST_Parent *parent) {
} }
} }
function void function void
parse__notes(Parser *p, AST_Parent *result) { parse__notes(Parser *p, AST_Parent *result) {
while(token_match(p, TK_At)) { while(token_match(p, TK_At)) {
Token *name = token_expect(p, TK_Identifier); Token *name = token_expect(p, TK_Identifier);
@@ -791,7 +791,7 @@ parse_decl(Parser *p, AST_Parent *parent){
"token '%s'", token_kind_string[token->kind]); "token '%s'", token_kind_string[token->kind]);
} }
} }
if(result){ if(result){
result->notes = note; result->notes = note;
ast_push_last(parent, result); ast_push_last(parent, result);
@@ -806,7 +806,7 @@ parse_decl(Parser *p, AST_Parent *parent){
function AST *parse_stmt(Parser *p); function AST *parse_stmt(Parser *p);
/* /*
stmt_list = '{' stmt* '}' stmt_list = '{' stmt* '}'
stmt = stmt =
| stmt_list | stmt_list
| 'return' expr ';' | 'return' expr ';'
| 'if' expr stmt_list | 'if' expr stmt_list
@@ -969,11 +969,11 @@ parse_stmt(Parser *p){
result = parse_simple_stmt(p); result = parse_simple_stmt(p);
token_expect(p, TK_Semicolon); token_expect(p, TK_Semicolon);
} }
if(result){ if(result){
result->notes = notes; result->notes = notes;
} }
return result; return result;
} }
@@ -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;
@@ -1083,11 +1083,11 @@ parse_test_expr(){
" 1>5 ? 1 : 2 " " 1>5 ? 1 : 2 "
" !!!!!1 " " !!!!!1 "
" ~~1 + -!2 " " ~~1 + -!2 "
" 1 + ++Thing[12]++ + ++Thing[12].expr +" " 1 + ++Thing[12]++ + ++Thing[12].expr +"
); );
Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr")); Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr"));
Parser *p = &parser; Parser *p = &parser;
S64 t = 5; S64 t = 5;
S64 test_val[] = { S64 test_val[] = {
(32+52-242*2/424%5-23), (32+52-242*2/424%5-23),
@@ -1106,7 +1106,7 @@ parse_test_expr(){
S64 val = eval_expr(expr); S64 val = eval_expr(expr);
assert(val == test_val[i]); assert(val == test_val[i]);
} }
String exprs[] = { String exprs[] = {
lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"), lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"),
lit("cast((thing: U32, qwe: *U32), (123+234))"), lit("cast((thing: U32, qwe: *U32), (123+234))"),
@@ -1123,7 +1123,7 @@ parse_test_expr(){
expr_print(expr); expr_print(expr);
printf("\n"); printf("\n");
} }
arena_end_scratch(); arena_end_scratch();
} }
@@ -1131,7 +1131,7 @@ function void
parse_test_decls(){ parse_test_decls(){
Arena *scratch = arena_begin_scratch(); Arena *scratch = arena_begin_scratch();
Parser p = parser_make(scratch); Parser p = parser_make(scratch);
String decls[] = { String decls[] = {
lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"), lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"),
lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"), lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"),
@@ -1156,7 +1156,7 @@ parse_test_from_file(){
arena_end_scratch(); arena_end_scratch();
} }
function void function void
parse_test_stmt(){ parse_test_stmt(){
Arena *scratch = arena_begin_scratch(); Arena *scratch = arena_begin_scratch();
Parser p = parser_make(scratch); Parser p = parser_make(scratch);

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,7 +1,5 @@
/* /*
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();
}