Starting from scratch on smaller scale, typechecking global and constant variables, compound expressions for arrays

This commit is contained in:
Krzosa Karol
2022-05-20 10:54:20 +02:00
parent d993623a50
commit 30736d37b6
12 changed files with 709 additions and 1307 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
*.pdb *.pdb
*.txt *.txt
*.4c *.4c
*.bin

View File

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

29
main.c
View File

@@ -1,29 +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 "os_win32.c"
#include "lex.c"
#include "ast.c"
#include "print.c"
#include "parse.c"
#include "type.c"
#include "resolve.c"
int main(){
lex_test();
parse_test();
ast_test();
intern_test();
map_test();
array_test();
test_types();
resolve_test();
}

1133
main.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -5,20 +5,29 @@
// 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_const;
Intern_String keyword_struct; Intern_String keyword_struct;
Intern_String keyword_union; Intern_String keyword_union;
Intern_String keyword_cast;
Intern_String keyword_enum; Intern_String keyword_enum;
Intern_String intern_void;
Intern_String intern_int;
Intern_String intern_str;
Intern_String intern_unsigned;
const U64 Parse_Ctx_ID = 115151; const U64 Parse_Ctx_ID = 115151;
struct Parse_Ctx:Lexer{ struct Parse_Ctx:Lexer{
Arena ast_arena; Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap;
Map global_syms;
Map type_map;
Token empty_token; Token empty_token;
S64 indent; S64 indent;
S64 pt[256]; // precedence table S64 pt[256]; // precedence table
Map type_map;
void init(){ void init(Allocator *perm_allocator, Allocator *heap_allocator){
const S64 addp = 1; const S64 addp = 1;
const S64 mulp = 2; const S64 mulp = 2;
pt[TK_Add] = addp; pt[TK_Add] = addp;
@@ -26,17 +35,28 @@ struct Parse_Ctx:Lexer{
pt[TK_Div] = mulp; pt[TK_Div] = mulp;
pt[TK_Mul] = mulp; pt[TK_Mul] = mulp;
arena_init(&ast_arena, "AST Arena"_s); perm = perm_allocator;
lex_init(this); heap = heap_allocator;
keyword_const = intern_string(&interns, "const"_s);
global_syms = {heap};
type_map = {heap};
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);
keyword_cast = intern_string(&interns, "cast"_s);
keyword_enum = intern_string(&interns, "enum"_s); keyword_enum = intern_string(&interns, "enum"_s);
interns.first_keyword = keyword_const.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_int = intern_string(&interns, "int"_s);
intern_str = intern_string(&interns, "String"_s);
intern_unsigned = intern_string(&interns, "unsigned"_s);
} }
}; };
thread_local Parse_Ctx *pctx;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// AST // AST
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -47,8 +67,11 @@ enum Ast_Kind{
AK_Expr_Str, AK_Expr_Str,
AK_Expr_Int, AK_Expr_Int,
AK_Expr_Cast,
AK_Expr_Ident, AK_Expr_Ident,
AK_Expr_Binary, AK_Expr_Binary,
AK_Expr_CompoundItem,
AK_Expr_Compound,
AK_Decl_Func, AK_Decl_Func,
AK_Decl_Func_Arg, AK_Decl_Func_Arg,
@@ -66,6 +89,7 @@ struct Ast{
Token *pos; Token *pos;
}; };
struct Ast_Typespec;
struct Ast_Expr:Ast{ struct Ast_Expr:Ast{
union{ union{
Intern_String intern_val; Intern_String intern_val;
@@ -75,6 +99,19 @@ struct Ast_Expr:Ast{
Ast_Expr *left; Ast_Expr *left;
Ast_Expr *right; Ast_Expr *right;
} binary; } binary;
struct{
Ast_Typespec *typespec;
Array<Ast_Expr *> exprs;
}compound;
struct{
Ast_Expr *name; // index | name
Ast_Expr *index;
Ast_Expr *item;
}compound_item;
struct{
Ast_Expr *expr;
Ast_Typespec *typespec;
}cast;
}; };
}; };
@@ -98,7 +135,6 @@ struct Ast_Decl:Ast{
union{ union{
struct{ struct{
Ast_Typespec *typespec; Ast_Typespec *typespec;
Intern_String name;
Ast_Expr *expr; Ast_Expr *expr;
}var; }var;
struct{ struct{
@@ -117,8 +153,7 @@ 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) \
Get_Ctx(Parse_Ctx); \ Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
Ast_##T *result = exp_alloc_type(&ctx->ast_arena, Ast_##T); \
result->kind = ikind; \ result->kind = ikind; \
result->pos = ipos result->pos = ipos
@@ -152,6 +187,31 @@ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
return result; return result;
} }
function Ast_Expr *
ast_expr_compound(Token *pos, Ast_Typespec *typespec, Array<Ast_Expr *> exprs){
AST_NEW(Expr, AK_Expr_Compound, pos);
result->compound.typespec = typespec;
result->compound.exprs = exprs.tight_copy(pctx->perm);
return result;
}
function Ast_Expr *
ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Expr *name, Ast_Expr *item){
AST_NEW(Expr, AK_Expr_CompoundItem, pos);
result->compound_item.name = name;
result->compound_item.index = index;
result->compound_item.item = item;
return result;
}
function Ast_Expr *
ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Typespec *typespec){
AST_NEW(Expr, AK_Expr_Cast, pos);
result->cast.expr = expr;
result->cast.typespec = typespec;
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Typespecs // Typespecs
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -177,6 +237,14 @@ ast_typespec_array(Token *pos, Ast_Typespec *base, Ast_Expr *expr){
return result; return result;
} }
function Ast_Typespec *
ast_typespec_func(Token *pos, Ast_Typespec *ret, Array<Ast_Typespec*> args){
AST_NEW(Typespec, AK_Typespec_Func, pos);
result->func.ret = ret;
result->func.args = args.tight_copy(pctx->perm);
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Declarations // Declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -196,9 +264,17 @@ ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *e
return result; return result;
} }
function Ast_Package * function Ast_Decl *
ast_package(Token *pos, String name){ ast_decl_const(Token *pos, Intern_String name, Ast_Expr *expr){
AST_NEW(Package, AK_Package, pos); Ast_Decl *result = ast_decl_var(pos, 0, name, expr);
result->name = intern_string(&ctx->interns, name); result->kind = AK_Decl_Const;
return result;
}
function Ast_Package *
ast_package(Token *pos, String name, Array<Ast_Decl *> decls){
AST_NEW(Package, AK_Package, pos);
result->decls = decls.tight_copy(pctx->perm);
result->name = intern_string(&pctx->interns, name);
return result; return result;
} }

View File

@@ -51,7 +51,6 @@ enum Token_Kind{
TK_Colon, TK_Colon,
TK_Assign, TK_Assign,
TK_ColonAssign,
TK_DivAssign, TK_DivAssign,
TK_MulAssign, TK_MulAssign,
TK_ModAssign, TK_ModAssign,
@@ -112,6 +111,7 @@ struct Lex_Stream{
U8 *line_begin; U8 *line_begin;
String file; String file;
S32 line; S32 line;
S32 inside_brace_paren;
}; };
struct Lexer{ struct Lexer{
@@ -169,7 +169,7 @@ lex_set_len(Lex_Stream *s, Token *token){
function void function void
lex_set_keywords(Lexer *lexer, Array<String> keywords){ lex_set_keywords(Lexer *lexer, Array<String> keywords){
Intern_String keyword = {}; Intern_String keyword = {};
IFor(keywords){ Iter(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;
@@ -272,14 +272,14 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
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;
case '(': t.kind = TK_OpenParen; break; case '(': s->inside_brace_paren++; t.kind = TK_OpenParen; break;
case ')': t.kind = TK_CloseParen; break; case ')': s->inside_brace_paren--; t.kind = TK_CloseParen; break;
case '{': t.kind = TK_OpenBrace; break; case '{': s->inside_brace_paren++; t.kind = TK_OpenBrace; break;
case '}': t.kind = TK_CloseBrace; break; case '}': s->inside_brace_paren--; t.kind = TK_CloseBrace; break;
case '[': t.kind = TK_OpenBracket; break; case '[': s->inside_brace_paren++; t.kind = TK_OpenBracket; break;
case ']': t.kind = TK_CloseBracket; break; case ']': s->inside_brace_paren--; t.kind = TK_CloseBracket; break;
case ',': t.kind = TK_Comma; break; case ',': t.kind = TK_Comma; break;
case '~': t.kind = TK_Neg; break; case '~': t.kind = TK_Neg; break;
case '?': t.kind = TK_Question; break; case '?': t.kind = TK_Question; break;
@@ -371,10 +371,6 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
lex_advance(s); lex_advance(s);
t.kind = TK_DoubleColon; t.kind = TK_DoubleColon;
} }
else if(lexc(s) == '='){
lex_advance(s);
t.kind = TK_ColonAssign;
}
else { else {
t.kind = TK_Colon; t.kind = TK_Colon;
} }
@@ -483,7 +479,10 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *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;
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);
@@ -494,15 +493,15 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
} }
function void function void
lex_init(Lexer *l){ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
l->tokens = array_make<Token>(1024*2); l->tokens = array_make<Token>(token_string_arena, 1024*2);
l->interns= intern_table_make(1024); l->interns= intern_table_make(token_string_arena, map_allocator, 1024);
} }
function Lexer function Lexer
lex_make(){ lex_make(Allocator *token_string_arena, Allocator *map_allocator){
Lexer result = {}; Lexer result = {};
lex_init(&result); lex_init(token_string_arena, map_allocator, &result);
return result; return result;
} }
@@ -515,29 +514,30 @@ lex_restream(Lexer *lexer, String istream, String file){
} }
function Lexer function Lexer
lex_stream(String istream, String file){ lex_stream(Allocator *token_string_arena, Allocator *map_allocator, String istream, String file){
Lexer result = lex_make(); Lexer result = lex_make(token_string_arena, map_allocator);
lex_restream(&result, istream, file); lex_restream(&result, istream, file);
return result; return result;
} }
function void function void
lex_test(){ Set_Scratch(); lex_test(){
Scratch scratch;
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 = {}; 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(); 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> array = 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,
@@ -546,7 +546,7 @@ lex_test(){ Set_Scratch();
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_ColonAssign, TK_End TK_Colon, TK_Assign, TK_End
}; };
String strs[] = { String strs[] = {
"Keyword"_s, "\n "_s, "18446744073709551616"_s,"{"_s,"}"_s,")"_s,"("_s, "Keyword"_s, "\n "_s, "18446744073709551616"_s,"{"_s,"}"_s,")"_s,"("_s,
@@ -554,18 +554,18 @@ lex_test(){ Set_Scratch();
"..."_s,"."_s,"->"_s,","_s,"::"_s,":"_s, "..."_s,"."_s,"->"_s,","_s,"::"_s,":"_s,
"Thing"_s,"Thingy"_s,"Test_Meme"_s, "+="_s,"-="_s, "Thing"_s,"Thingy"_s,"Test_Meme"_s, "+="_s,"-="_s,
"=="_s,"42524"_s,"4294967295"_s,"18446744073709551615"_s, "=="_s,"42524"_s,"4294967295"_s,"18446744073709551615"_s,
"for"_s, "if"_s, "while"_s, "switch"_s, ":="_s, ""_s, "for"_s, "if"_s, "while"_s, "switch"_s, ":"_s, "="_s, ""_s,
}; };
U64 vals[] = { U64 vals[] = {
42524, 4294967295, 18446744073709551615llu 42524, 4294967295, 18446744073709551615llu
}; };
int ui = 0; int ui = 0;
For(array, t, i){ For(arr){
assert(t->kind == kind[i]); assert(it->kind == kind[i]);
assert(string_compare(t->string, strs[i])); assert(string_compare(it->string, strs[i]));
if(t->kind == TK_Integer){ if(it->kind == TK_Integer){
assert(t->int_val == vals[ui++]); assert(it->int_val == vals[ui++]);
} }
} }
} }
@@ -603,7 +603,6 @@ token_kind_string(Token_Kind kind){
case TK_GreaterThen: return ">"_s; case TK_GreaterThen: return ">"_s;
case TK_Colon: return ":"_s; case TK_Colon: return ":"_s;
case TK_Assign: return "="_s; case TK_Assign: return "="_s;
case TK_ColonAssign: return ":="_s;
case TK_DivAssign: return "/="_s; case TK_DivAssign: return "/="_s;
case TK_MulAssign: return "*="_s; case TK_MulAssign: return "*="_s;
case TK_ModAssign: return "%="_s; case TK_ModAssign: return "%="_s;
@@ -629,6 +628,7 @@ token_kind_string(Token_Kind kind){
case TK_LeftShift: return "<<"_s; case TK_LeftShift: return "<<"_s;
case TK_RightShift: return ">>"_s; case TK_RightShift: return ">>"_s;
case TK_Arrow: return "->"_s; case TK_Arrow: return "->"_s;
case TK_NewLine: return "NewLine"_s;
case TK_ExprSizeof: return "sizeof"_s; case TK_ExprSizeof: return "sizeof"_s;
case TK_DocComment: return "DocComment"_s; case TK_DocComment: return "DocComment"_s;
case TK_Comment: return "Comment"_s; case TK_Comment: return "Comment"_s;

View File

@@ -1,22 +1,22 @@
function Token * function Token *
token_get(S64 i = 0){ Get_Ctx(Parse_Ctx); token_get(S64 i = 0){
i += ctx->token_iter; i += pctx->token_iter;
if(i >= ctx->tokens.len){ if(i >= pctx->tokens.len){
return &ctx->empty_token; return &pctx->empty_token;
} }
Token *result = &ctx->tokens[i]; Token *result = &pctx->tokens[i];
if(result->kind == TK_NewLine){ if(result->kind == TK_NewLine){
ctx->indent = result->indent; pctx->indent = result->indent;
} }
return result; return result;
} }
function Token * function Token *
token_next(){ Get_Ctx(Parse_Ctx); token_next(){
Token *token = token_get(); Token *token = token_get();
ctx->token_iter++; pctx->token_iter++;
return token; return token;
} }
@@ -52,8 +52,8 @@ token_match_keyword(Intern_String string){
function void function void
parsing_error(Token *token, const char *str, ...){ parsing_error(Token *token, const char *str, ...){
Set_Scratch(); Scratch scratch;
STRING_FMT(imp_get(), 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);
@@ -122,6 +122,41 @@ Compound literals
- { } - { }
*/ */
function Ast_Expr *parse_expr(S64 rbp = 0); function Ast_Expr *parse_expr(S64 rbp = 0);
function Ast_Typespec *parse_typespec();
function Ast_Expr *
parse_expr_compound(){
Scratch scratch;
Token *pos = token_get();
Array<Ast_Expr *> exprs = {scratch};
while(!token_is(TK_CloseBrace)){
Token *token = token_get();
Ast_Expr *index = 0;
Ast_Expr *name = 0;
if(token_match(TK_OpenBracket)){
index = parse_expr();
token_expect(TK_CloseBracket);
token_expect(TK_Assign);
}
else if(token_is(TK_Identifier)){
token = token_next();
name = ast_expr_identifier(token, token->intern_val);
token_expect(TK_Assign);
}
Ast_Expr *item = parse_expr();
Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item);
exprs.add(item_comp);
if(!token_match(TK_Comma)){
break;
}
}
token_expect(TK_CloseBrace);
Ast_Expr *result = ast_expr_compound(pos, 0, exprs);
return result;
}
function Ast_Expr * function Ast_Expr *
parse_expr_nud(Token *token){ parse_expr_nud(Token *token){
@@ -129,14 +164,29 @@ parse_expr_nud(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_Keyword: {
if(token->intern_val == keyword_cast){
token_expect(TK_OpenParen);
Ast_Expr *expr = parse_expr();
token_expect(TK_Colon);
Ast_Typespec *typespec = parse_typespec();
token_expect(TK_CloseParen);
return ast_expr_cast(token, expr, typespec);
}
else {
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
return 0;
}
}break;
case TK_OpenBrace: return parse_expr_compound();
case TK_OpenParen: {Ast_Expr *result = parse_expr(); token_expect(TK_CloseParen); return result;} case TK_OpenParen: {Ast_Expr *result = parse_expr(); token_expect(TK_CloseParen); return result;}
default: parsing_error(token, "Unexpected token of kind: [%s] in expression", token_kind_string(token->kind).str); return 0; default: parsing_error(token, "Unexpected token of kind: [%s] in expression", token_kind_string(token->kind).str); return 0;
} }
} }
function S64 function S64
op_precedence(Token_Kind kind){ Get_Ctx(Parse_Ctx); op_precedence(Token_Kind kind){
S64 result = ctx->pt[kind]; S64 result = pctx->pt[kind];
return result; return result;
} }
@@ -183,22 +233,22 @@ expr_eval(Ast_Expr *expr){
} }
#define TEST_PARSER() \ #define TEST_PARSER() \
Set_Scratch(); \ Scratch scratch(thread_ctx.scratch);\
Parse_Ctx ctx = {}; \ Parse_Ctx ctx = {}; \
ctx.init(); \ ctx.init(scratch, scratch); \
Set_Ctx(&ctx, Parse_Ctx_ID) pctx = &ctx
function void function void
test_parse_expr(){ test_parse_expr(){
TEST_PARSER(); TEST_PARSER();
struct Test{String str;S64 val;}; struct Test{String str;S64 val;};
Array<Test> exprs = {}; Array<Test> exprs = {scratch};
exprs.add({"(4+5)*2"_s, (4+5)*2}); exprs.add({"(4+5)*2"_s, (4+5)*2});
exprs.add({"4+5*2"_s, 4+5*2}); exprs.add({"4+5*2"_s, 4+5*2});
exprs.add({"4*5+5"_s, 4*5+5}); exprs.add({"4*5+5"_s, 4*5+5});
exprs.add({"4+5+5+3"_s, 4+5+5+3}); exprs.add({"4+5+5+3"_s, 4+5+5+3});
For(exprs,it,i){ Iter(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);
@@ -209,38 +259,115 @@ test_parse_expr(){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Parsing declarations // Parsing declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function Ast_Decl * function Ast_Typespec *
parse_decl(){Get_Ctx(Parse_Ctx); parse_optional_type(){
Ast_Decl *result = 0; Ast_Typespec *result = 0;
Token *token = token_match(TK_Identifier); if(token_match(TK_Colon)) result = parse_typespec();
if(token){ return result;
if(token_match(TK_ColonAssign)){ }
if(ctx->indent != 0)
parsing_error(token, "Top level declarations shouldn't be indented");
Ast_Expr *expr = parse_expr(); function Ast_Typespec *
result = ast_decl_var(token, 0, token->intern_val, expr); parse_typespec_function(Token *token){
Scratch scratch;
Array<Ast_Typespec *> args = {scratch};
if(!token_is(TK_CloseParen)) {
for(;;) {
args.add(parse_typespec());
if(!token_match(TK_Comma)){
break;
} }
else parsing_error(token, "Encountered unexpected token while parsing a top level declarations"); }
}
token_expect(TK_CloseParen);
Ast_Typespec *ret = parse_optional_type();
Ast_Typespec *result = ast_typespec_func(token, ret, args);
return result;
}
// [10]*int - Array of 10 pointers to ints
function Ast_Typespec *
parse_typespec_recurse(){
Token *token = token_get();
if(token_match(TK_Mul)){
Ast_Typespec *result = parse_typespec_recurse();
result = ast_typespec_pointer(token, result);
return result;
}
else if(token_match(TK_OpenBracket)){
Ast_Expr *expr = parse_expr();
token_expect(TK_CloseBracket);
Ast_Typespec *result = parse_typespec_recurse();
result = ast_typespec_array(token, result, expr);
return result;
}
else if(token_match(TK_OpenParen)){
Ast_Typespec *result = parse_typespec_function(token);
return result;
}
else if(token_match(TK_Identifier)){
Ast_Typespec *result = ast_typespec_name(token, token->intern_val);
return result;
}
else{
parsing_error(token, "Failed to parse type, unexpected token of kind", token_kind_string(token->kind).str);
return 0;
}
}
function Ast_Typespec *
parse_typespec(){
Ast_Typespec *result = parse_typespec_recurse();
return result;
}
function Ast_Expr *
parse_assign_expr(){
Ast_Expr *result = 0;
if(token_match(TK_Assign)) result = parse_expr();
return result;
}
function Ast_Decl *
parse_decl(){
Ast_Decl *result = 0;
if(token_is(TK_Identifier)){
if(pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented");
Token *name = token_next();
if(token_match(TK_DoubleColon)){ // Constant
Ast_Expr *expr = parse_expr();
result = ast_decl_const(name, name->intern_val, expr);
}
else if(token_match(TK_Colon)){
Ast_Typespec *typespec = 0;
Ast_Expr *expr = 0;
if(!token_is(TK_Assign)) typespec = parse_typespec();
if(token_match(TK_Assign)) expr = parse_expr();
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
result = ast_decl_var(name, typespec, name->intern_val, expr);
}
else{
Token *token = token_get();
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
}
} }
return result; return result;
} }
function Ast_Package * function Ast_Package *
parse_file(){ parse_file(){
Ast_Package *result = ast_package(token_get(), token_get()->file); Scratch scratch;
Token *token = token_get();
Array<Ast_Decl *>decls = {scratch};
while(!token_is(TK_End)){ while(!token_is(TK_End)){
while(token_match(TK_NewLine)); while(token_match(TK_NewLine));
Ast_Decl *decl = parse_decl(); Ast_Decl *decl = parse_decl();
if(!decl) break; if(!decl) break;
result->decls.add(decl); decls.add(decl);
} }
Ast_Package *result = ast_package(token, token->file, decls);
return result; return result;
} }
function void
test_parse_decl(){
TEST_PARSER();
lex_restream(&ctx, "thing := 24252\nanother_thing := \"string\"\n\nref := thing"_s, "test_parse_decl"_s);
Ast_Package *result = parse_file();
}

309
new_resolve.cpp Normal file
View File

@@ -0,0 +1,309 @@
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
#define Ast_End() } break
enum Sym_Kind{
SYM_None,
SYM_Type,
SYM_Const,
SYM_Var,
};
struct Sym{
Intern_String name;
Sym_Kind kind;
Ast_Decl *decl;
Type *type;
union{
S64 int_val;
Intern_String intern_val;
};
};
struct Operand{
Type *type;
bool is_const;
union {
S64 int_val;
Intern_String intern_val;
};
};
function void
sym_insert(Sym *sym){
U64 hash = hash_string(sym->name.s);
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
if(is_sym){
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
}
map_insert_u64(&pctx->global_syms, hash, sym);
}
function Sym *
sym_get(Intern_String name){
Sym *result = (Sym *)map_get_u64(&pctx->global_syms, hash_string(name.s));
return result;
}
function Sym *
sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
Sym *result = exp_alloc_type(pctx->perm, Sym);
result->name = name;
result->kind = kind;
result->type = type;
result->decl = decl;
return result;
}
global Ast_Decl empty_decl = {};
function void
sym_insert_builtin_type(String name, Type *type){
Intern_String string = intern_string(&pctx->interns, name);
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
sym_insert(sym);
}
function void
sym_insert_builtins(){
sym_insert_builtin_type("void"_s, type_void);
sym_insert_builtin_type("bool"_s, type_bool);
sym_insert_builtin_type("int"_s, type_int);
sym_insert_builtin_type("String"_s, type_string);
{
Intern_String string = intern_string(&pctx->interns, "true"_s);
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
sym_insert(sym);
}
{
Intern_String string = intern_string(&pctx->interns, "false"_s);
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
sym_insert(sym);
}
{
Intern_String string = intern_string(&pctx->interns, "null"_s);
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
sym_insert(sym);
}
}
function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0);
function Type *
eval_typespec(Ast_Typespec *ast){
if(!ast) return 0;
switch(ast->kind){
Ast_Begin(AK_Typespec_Ident, Ast_Typespec){
Sym *type_sym = sym_get(node->name);
if(!type_sym){
parsing_error(node->pos, "This type is not defined");
}
if(type_sym->kind != SYM_Type){
parsing_error(node->pos, "This identifier is not a type");
}
return type_sym->type;
Ast_End();
}
Ast_Begin(AK_Typespec_Pointer, Ast_Typespec){
Type *type = eval_typespec(node->base);
Type *result = type_pointer(type);
return result;
Ast_End();
}
Ast_Begin(AK_Typespec_Array, Ast_Typespec){
Type *type = eval_typespec(node->arr.base);
Operand expr = eval_expr(node->arr.expr);
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");
Type *result = type_array(type, expr.int_val);
return result;
Ast_End();
}
invalid_default_case;
}
return 0;
}
function Type *
resolve_type_pair(Token *pos, Type *a, Type *b){
Type *result = 0;
if(!a && b) result = b;
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{ // a && b
if(b->kind == TYPE_Null) result = a;
else if(a->kind == TYPE_Null) result = b;
else if(a != b) parsing_error(pos, "Expression and type specification are differing");
else result = a; // Types are the same
}
return result;
}
function Operand
eval_expr(Ast_Expr *ast, Type *exp_compound_type){
switch(ast->kind){
Ast_Begin(AK_Expr_Int, Ast_Expr){
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
return result;
Ast_End();
}
Ast_Begin(AK_Expr_Str, Ast_Expr){
Operand result = {type_string, true, {.intern_val = node->intern_val}};
return result;
Ast_End();
}
Ast_Begin(AK_Expr_Compound, Ast_Expr){
Type *type = eval_typespec(node->compound.typespec);
Type *variable_type = exp_compound_type;
if(!type && variable_type) type = variable_type;
else if(!variable_type && type);
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
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");
Type *item_type = type->arr.base;
For(node->compound.exprs){
assert(it[0]->kind == AK_Expr_CompoundItem);
if(it[0]->compound_item.name) parsing_error(it[0]->pos, "Invalid array indexing in compound expression");
if(it[0]->compound_item.index){
Operand index_op = eval_expr(it[0]->compound_item.index);
if(!index_op.is_const) parsing_error(it[0]->pos, "Index in a compound expression is not a constant");
if(index_op.type != type_int) parsing_error(it[0]->pos, "Index should be of type int");
if(index_op.int_val > (type->arr.size - 1)) parsing_error(it[0]->pos, "Invalid index in compound expression, larger then type can store");
}
Operand expr = eval_expr(it[0]->compound_item.item);
if(expr.type != item_type) parsing_error(it[0]->pos, "Invalid type of item in compound expression");
}
}
else parsing_error(node->pos, "Invalid compound expression type");
Operand result = {type, false};
return result;
Ast_End();
}
Ast_Begin(AK_Expr_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(AK_Expr_Cast, Ast_Expr){
Operand expr = eval_expr(node->cast.expr);
Type *type = eval_typespec(node->cast.typespec);
if(type == expr.type) return expr;
else if(expr.type == type_int && type == type_bool){
expr.type = type_bool;
return expr;
}
else if(expr.type == type_bool && type == type_int){
expr.type = type_int;
return expr;
}
else if(expr.type == type_null){
expr.type = type;
return expr;
}
else parsing_error(node->pos, "Failed to cast, incompatible types");
Ast_End();
}
Ast_Begin(AK_Expr_Binary, Ast_Expr){
Operand left = eval_expr(ast->binary.left);
Operand right = eval_expr(ast->binary.right);
Operand result = {};
result.type = resolve_type_pair(node->pos, left.type, right.type);
if(left.is_const && right.is_const){
result.is_const = true;
if(result.type == type_int){
switch(node->binary.op){
case TK_Add: result.int_val = left.int_val + right.int_val; break;
case TK_Sub: result.int_val = left.int_val - right.int_val; break;
case TK_Mul: result.int_val = left.int_val * right.int_val; break;
case TK_Div: result.int_val = left.int_val / right.int_val; break;
invalid_default_case;
}
}
else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported");
}
return result;
Ast_End();
}
invalid_default_case;
}
return {};
}
function void
eval_decl(Ast *ast){
switch(ast->kind){
Ast_Begin(AK_Package, Ast_Package){
For(node->decls) eval_decl(*it);
Ast_End();
}
Ast_Begin(AK_Decl_Var, Ast_Decl){
Type *type = eval_typespec(node->var.typespec);
Operand expr = eval_expr(node->var.expr, type);
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
sym_insert(sym);
Ast_End();
}
Ast_Begin(AK_Decl_Const, Ast_Decl){
Type *type = eval_typespec(node->var.typespec);
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
Operand expr = eval_expr(node->var.expr);
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");
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
if(resolved_type == type_int) sym->int_val = expr.int_val;
else if(resolved_type == type_string) sym->intern_val = expr.intern_val;
sym_insert(sym);
Ast_End();
}
invalid_default_case;
}
}
function void
test_resolve(){
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);
}

View File

@@ -1,7 +1,9 @@
enum Type_Kind{ enum Type_Kind{
TYPE_None, TYPE_None,
TYPE_Null,
TYPE_Int, TYPE_Int,
TYPE_Bool,
TYPE_Unsigned,
TYPE_String, TYPE_String,
TYPE_Void, TYPE_Void,
TYPE_Pointer, TYPE_Pointer,
@@ -12,6 +14,22 @@ enum Type_Kind{
TYPE_Enum, TYPE_Enum,
}; };
const char *type_names[] = {
"[Invalid Type]",
"[TYPE_Null]",
"[TYPE_Int]",
"[TYPE_Bool]",
"[TYPE_Unsigned]",
"[TYPE_String]",
"[TYPE_Void]",
"[TYPE_Pointer]",
"[TYPE_Array]",
"[TYPE_Func]",
"[TYPE_Struct]",
"[TYPE_Union]",
"[TYPE_Enum]",
};
struct Type{ struct Type{
Type_Kind kind; Type_Kind kind;
SizeU size; SizeU size;
@@ -32,13 +50,19 @@ 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 Type type__void = {TYPE_Void}; global Type type__void = {TYPE_Void};
global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)}; global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
global Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
global Type type__string = {TYPE_String, sizeof(String), __alignof(String)}; global Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
global Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
global Type *type_void = &type__void; global Type *type_void = &type__void;
global Type *type_int = &type__int; global Type *type_int = &type__int;
global Type *type_unsigned = &type__unsigned;
global Type *type_string = &type__string; global Type *type_string = &type__string;
global Type *type_bool = &type__bool;
global Type *type_null = &type__null;
function Type * function Type *
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){ type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){
@@ -58,12 +82,11 @@ type_copy(Allocator *a, Type *type){
function Type * function Type *
type_pointer(Type *base){ type_pointer(Type *base){
Get_Ctx(Parse_Ctx); Type *result = (Type *)map_get(&pctx->type_map, (void *)base);
Type *result = (Type *)map_get(&ctx->type_map, (void *)base);
if(!result){ if(!result){
result = type_new(&ctx->ast_arena, TYPE_Pointer, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
result->base = base; result->base = base;
map_insert(&ctx->type_map, base, result); map_insert(&pctx->type_map, base, result);
} }
assert(result->kind == TYPE_Pointer); assert(result->kind == TYPE_Pointer);
return result; return result;
@@ -71,9 +94,8 @@ type_pointer(Type *base){
function Type * function Type *
type_array(Type *base, SizeU size){ type_array(Type *base, SizeU size){
Get_Ctx(Parse_Ctx);
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(&ctx->type_map, hash); Type *result = (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);
@@ -81,44 +103,40 @@ type_array(Type *base, SizeU size){
return result; return result;
} }
result = type_new(&ctx->ast_arena, 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;
map_insert_u64(&ctx->type_map, hash, result); map_insert_u64(&pctx->type_map, hash, result);
return result; return result;
} }
function Type * function Type *
type_function(Type *ret, Array<Type *> args){ type_function(Type *ret, Array<Type *> args){
Get_Ctx(Parse_Ctx);
U64 hash = hash_ptr(ret); U64 hash = hash_ptr(ret);
IFor(args){ For(args) hash = hash_mix(hash, hash_ptr(*it));
hash = hash_mix(hash, hash_ptr(*it)); Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
}
Type *result = (Type *)map_get_u64(&ctx->type_map, hash);
if(result){ if(result){
assert(result->kind == TYPE_Func); assert(result->kind == TYPE_Func);
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(&ctx->ast_arena, TYPE_Func, pointer_size, pointer_align);
result = type_new(pctx->perm, TYPE_Func, pointer_size, pointer_align);
result->func.ret = ret; result->func.ret = ret;
result->func.args = args.copy(&ctx->ast_arena); result->func.args = args.tight_copy(pctx->perm);
map_insert_u64(&ctx->type_map, hash, result); map_insert_u64(&pctx->type_map, hash, result);
return result; return result;
} }
function void function void
test_types(){ test_types(){
Set_Backup_Scratch(); Scratch scratch;
Set_Scratch();
Parse_Ctx ctx = {}; Parse_Ctx ctx = {};
Set_Ctx(&ctx, Parse_Ctx_ID); ctx.init(scratch, scratch);
ctx.ast_arena = thread_ctx.scratch[1]; pctx = &ctx;
Type *array_type1 = type_array(type_int, 32); Type *array_type1 = type_array(type_int, 32);
Type *array_type2 = type_array(type_int, 32); Type *array_type2 = type_array(type_int, 32);
@@ -133,13 +151,13 @@ test_types(){
assert(pointer_type3 != pointer_type1); assert(pointer_type3 != pointer_type1);
assert(pointer_type3 == pointer_type4); assert(pointer_type3 == pointer_type4);
Array<Type*> types = {}; Array<Type*> types = {scratch};
types.add(type_array(type_int, 32)); types.add(type_array(type_int, 32));
Type *func_type1 = type_function(types[0], types); Type *func_type1 = type_function(types[0], types);
Type *func_type2 = type_function(types[0], types); Type *func_type2 = type_function(types[0], types);
assert(func_type1 == func_type2); assert(func_type1 == func_type2);
Array<Type*> types2 = {}; Array<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);

View File

@@ -1,23 +1,6 @@
function S32 os_main(); function S32 os_main();
const SizeU page_size = 4096; const SizeU page_size = 4096;
function String
os_read_file(Arena *arena, String name){
String result = {0};
FILE *f = fopen((char *)name.str, "rb");
assert(f);
fseek(f, 0, SEEK_END);
result.len = ftell(f);
fseek(f, 0, SEEK_SET);
result.str = (U8 *)arena_push_size(arena, result.len + 1);
fread(result.str, result.len, 1, f);
fclose(f);
result.str[result.len] = 0;
return result;
}
function SizeU function SizeU
get_align_offset(SizeU size, SizeU align){ get_align_offset(SizeU size, SizeU align){
SizeU mask = align - 1; SizeU mask = align - 1;

View File

@@ -1,28 +0,0 @@
typedef struct Sym Sym;
typedef enum Sym_Kind{
Sym_Kind_None,
Sym_Kind_Type,
Sym_Kind_Const,
Sym_Kind_Func,
}Sym_Kind;
typedef enum Sym_State{
Sym_State_NotVisited,
Sym_State_Visited,
};
struct Sym{
Sym_Kind kind;
Sym_State state;
AST *ast;
Type *type;
};
global Sym *global_syms;
function void
resolve_test(){
}

58
test3.kl Normal file
View File

@@ -0,0 +1,58 @@
boolean: bool = true
value_of_bool: int = cast(boolean: int)
base := null
array1: [4]int = {1,2,3,4}
array2: [32]int = {1,2,3,4}
array3: [32]int = {
[0] = 0,
[31] = 31,
}
/*
pointer: *int
variable: int = *pointer
pointer_from_var := ^variable
pointer := &base
base_from_pointer := *pointer
structure: Data = {}
array2: [4]int = {
[0] = 0,
[1] = 1
}
array_to_pointer: *[4]int = &array1
array_to_pointer_imp : = &array1
*/
//-----------------------------------------------------------------------------
// Implicit type
//-----------------------------------------------------------------------------
implicit_int :: 10
implicit_str :: "Hello world"
//-----------------------------------------------------------------------------
// Pointers
//-----------------------------------------------------------------------------
pointer: *int = cast(null: *int)
pointer2: *int = null
pointer3: **int = null
//-----------------------------------------------------------------------------
// String types
//-----------------------------------------------------------------------------
string1 :: "Test"
string2 :: string1
//-----------------------------------------------------------------------------
// Constant int variables
//-----------------------------------------------------------------------------
thing0 :: 10
thing1 :: thing0 + 11
thing2 :: thing1 + 20
combin :: thing0 + thing1 + thing2