Starting from scratch on smaller scale, typechecking global and constant variables, compound expressions for arrays
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,4 +2,5 @@
|
|||||||
*.ilk
|
*.ilk
|
||||||
*.pdb
|
*.pdb
|
||||||
*.txt
|
*.txt
|
||||||
*.4c
|
*.4c
|
||||||
|
*.bin
|
||||||
@@ -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
29
main.c
@@ -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();
|
|
||||||
}
|
|
||||||
102
new_ast.cpp
102
new_ast.cpp
@@ -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_Decl *
|
||||||
|
ast_decl_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
||||||
|
Ast_Decl *result = ast_decl_var(pos, 0, name, expr);
|
||||||
|
result->kind = AK_Decl_Const;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function Ast_Package *
|
function Ast_Package *
|
||||||
ast_package(Token *pos, String name){
|
ast_package(Token *pos, String name, Array<Ast_Decl *> decls){
|
||||||
AST_NEW(Package, AK_Package, pos);
|
AST_NEW(Package, AK_Package, pos);
|
||||||
result->name = intern_string(&ctx->interns, name);
|
result->decls = decls.tight_copy(pctx->perm);
|
||||||
|
result->name = intern_string(&pctx->interns, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
66
new_lex.cpp
66
new_lex.cpp
@@ -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);
|
||||||
|
|
||||||
array->add(t);
|
B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0;
|
||||||
|
if(!skip){
|
||||||
|
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;
|
||||||
|
|||||||
205
new_parse.cpp
205
new_parse.cpp
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,23 +232,23 @@ expr_eval(Ast_Expr *expr){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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");
|
function Ast_Typespec *
|
||||||
|
parse_typespec_function(Token *token){
|
||||||
Ast_Expr *expr = parse_expr();
|
Scratch scratch;
|
||||||
result = ast_decl_var(token, 0, token->intern_val, expr);
|
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
309
new_resolve.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
66
new_type.cpp
66
new_type.cpp
@@ -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);
|
||||||
|
|||||||
17
os_win32.c
17
os_win32.c
@@ -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;
|
||||||
|
|||||||
28
resolve.c
28
resolve.c
@@ -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
58
test3.kl
Normal 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
|
||||||
Reference in New Issue
Block a user