Starting from scratch on smaller scale, typechecking global and constant variables, compound expressions for arrays
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
*.pdb
|
||||
*.txt
|
||||
*.4c
|
||||
*.bin
|
||||
@@ -1,3 +1,3 @@
|
||||
@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();
|
||||
}
|
||||
106
new_ast.cpp
106
new_ast.cpp
@@ -5,20 +5,29 @@
|
||||
// Parser::ast_arena - arena for asts
|
||||
// Lexer::interns::string_allocator - arena for interns
|
||||
//
|
||||
Intern_String keyword_const;
|
||||
Intern_String keyword_struct;
|
||||
Intern_String keyword_union;
|
||||
Intern_String keyword_cast;
|
||||
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;
|
||||
struct Parse_Ctx:Lexer{
|
||||
Arena ast_arena;
|
||||
Allocator *perm; // Stores: AST, tokens, interns
|
||||
Allocator *heap;
|
||||
|
||||
Map global_syms;
|
||||
Map type_map;
|
||||
|
||||
Token empty_token;
|
||||
S64 indent;
|
||||
S64 pt[256]; // precedence table
|
||||
Map type_map;
|
||||
|
||||
void init(){
|
||||
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
||||
const S64 addp = 1;
|
||||
const S64 mulp = 2;
|
||||
pt[TK_Add] = addp;
|
||||
@@ -26,17 +35,28 @@ struct Parse_Ctx:Lexer{
|
||||
pt[TK_Div] = mulp;
|
||||
pt[TK_Mul] = mulp;
|
||||
|
||||
arena_init(&ast_arena, "AST Arena"_s);
|
||||
lex_init(this);
|
||||
keyword_const = intern_string(&interns, "const"_s);
|
||||
perm = perm_allocator;
|
||||
heap = heap_allocator;
|
||||
|
||||
global_syms = {heap};
|
||||
type_map = {heap};
|
||||
|
||||
lex_init(perm, heap, this);
|
||||
keyword_struct= intern_string(&interns, "struct"_s);
|
||||
keyword_union = intern_string(&interns, "union"_s);
|
||||
keyword_cast = intern_string(&interns, "cast"_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;
|
||||
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -47,8 +67,11 @@ enum Ast_Kind{
|
||||
|
||||
AK_Expr_Str,
|
||||
AK_Expr_Int,
|
||||
AK_Expr_Cast,
|
||||
AK_Expr_Ident,
|
||||
AK_Expr_Binary,
|
||||
AK_Expr_CompoundItem,
|
||||
AK_Expr_Compound,
|
||||
|
||||
AK_Decl_Func,
|
||||
AK_Decl_Func_Arg,
|
||||
@@ -66,6 +89,7 @@ struct Ast{
|
||||
Token *pos;
|
||||
};
|
||||
|
||||
struct Ast_Typespec;
|
||||
struct Ast_Expr:Ast{
|
||||
union{
|
||||
Intern_String intern_val;
|
||||
@@ -75,6 +99,19 @@ struct Ast_Expr:Ast{
|
||||
Ast_Expr *left;
|
||||
Ast_Expr *right;
|
||||
} 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{
|
||||
struct{
|
||||
Ast_Typespec *typespec;
|
||||
Intern_String name;
|
||||
Ast_Expr *expr;
|
||||
}var;
|
||||
struct{
|
||||
@@ -117,8 +153,7 @@ struct Ast_Package:Ast{
|
||||
// AST Constructors beginning with expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
#define AST_NEW(T,ikind,ipos) \
|
||||
Get_Ctx(Parse_Ctx); \
|
||||
Ast_##T *result = exp_alloc_type(&ctx->ast_arena, Ast_##T); \
|
||||
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
||||
result->kind = ikind; \
|
||||
result->pos = ipos
|
||||
|
||||
@@ -152,6 +187,31 @@ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -177,6 +237,14 @@ ast_typespec_array(Token *pos, Ast_Typespec *base, Ast_Expr *expr){
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -196,9 +264,17 @@ ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *e
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Package *
|
||||
ast_package(Token *pos, String name){
|
||||
AST_NEW(Package, AK_Package, pos);
|
||||
result->name = intern_string(&ctx->interns, name);
|
||||
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 *
|
||||
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;
|
||||
}
|
||||
62
new_lex.cpp
62
new_lex.cpp
@@ -51,7 +51,6 @@ enum Token_Kind{
|
||||
TK_Colon,
|
||||
|
||||
TK_Assign,
|
||||
TK_ColonAssign,
|
||||
TK_DivAssign,
|
||||
TK_MulAssign,
|
||||
TK_ModAssign,
|
||||
@@ -112,6 +111,7 @@ struct Lex_Stream{
|
||||
U8 *line_begin;
|
||||
String file;
|
||||
S32 line;
|
||||
S32 inside_brace_paren;
|
||||
};
|
||||
|
||||
struct Lexer{
|
||||
@@ -169,7 +169,7 @@ lex_set_len(Lex_Stream *s, Token *token){
|
||||
function void
|
||||
lex_set_keywords(Lexer *lexer, Array<String> keywords){
|
||||
Intern_String keyword = {};
|
||||
IFor(keywords){
|
||||
Iter(keywords){
|
||||
keyword = intern_string(&lexer->interns, *it);
|
||||
if(it == keywords.begin())
|
||||
lexer->interns.first_keyword = keyword.str;
|
||||
@@ -274,12 +274,12 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
switch(*t.str){
|
||||
case 0 : break;
|
||||
case '@': t.kind = TK_At; break;
|
||||
case '(': t.kind = TK_OpenParen; break;
|
||||
case ')': t.kind = TK_CloseParen; break;
|
||||
case '{': t.kind = TK_OpenBrace; break;
|
||||
case '}': t.kind = TK_CloseBrace; break;
|
||||
case '[': t.kind = TK_OpenBracket; break;
|
||||
case ']': t.kind = TK_CloseBracket; break;
|
||||
case '(': s->inside_brace_paren++; t.kind = TK_OpenParen; break;
|
||||
case ')': s->inside_brace_paren--; t.kind = TK_CloseParen; break;
|
||||
case '{': s->inside_brace_paren++; t.kind = TK_OpenBrace; break;
|
||||
case '}': s->inside_brace_paren--; t.kind = TK_CloseBrace; break;
|
||||
case '[': s->inside_brace_paren++; t.kind = TK_OpenBracket; break;
|
||||
case ']': s->inside_brace_paren--; t.kind = TK_CloseBracket; break;
|
||||
case ',': t.kind = TK_Comma; break;
|
||||
case '~': t.kind = TK_Neg; 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);
|
||||
t.kind = TK_DoubleColon;
|
||||
}
|
||||
else if(lexc(s) == '='){
|
||||
lex_advance(s);
|
||||
t.kind = TK_ColonAssign;
|
||||
}
|
||||
else {
|
||||
t.kind = TK_Colon;
|
||||
}
|
||||
@@ -483,7 +479,10 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
if(t.len==0)
|
||||
lex_set_len(s,&t);
|
||||
|
||||
B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0;
|
||||
if(!skip){
|
||||
array->add(t);
|
||||
}
|
||||
|
||||
while(lex_is_whitespace(lexc(s)))
|
||||
lex_advance(s);
|
||||
@@ -494,15 +493,15 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
}
|
||||
|
||||
function void
|
||||
lex_init(Lexer *l){
|
||||
l->tokens = array_make<Token>(1024*2);
|
||||
l->interns= intern_table_make(1024);
|
||||
lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
||||
l->tokens = array_make<Token>(token_string_arena, 1024*2);
|
||||
l->interns= intern_table_make(token_string_arena, map_allocator, 1024);
|
||||
}
|
||||
|
||||
function Lexer
|
||||
lex_make(){
|
||||
lex_make(Allocator *token_string_arena, Allocator *map_allocator){
|
||||
Lexer result = {};
|
||||
lex_init(&result);
|
||||
lex_init(token_string_arena, map_allocator, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -515,29 +514,30 @@ lex_restream(Lexer *lexer, String istream, String file){
|
||||
}
|
||||
|
||||
function Lexer
|
||||
lex_stream(String istream, String file){
|
||||
Lexer result = lex_make();
|
||||
lex_stream(Allocator *token_string_arena, Allocator *map_allocator, String istream, String file){
|
||||
Lexer result = lex_make(token_string_arena, map_allocator);
|
||||
lex_restream(&result, istream, file);
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
lex_test(){ Set_Scratch();
|
||||
lex_test(){
|
||||
Scratch scratch;
|
||||
String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\" Thingy"
|
||||
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
||||
"for if while switch :="_s;
|
||||
|
||||
Array<String> keywords = {};
|
||||
Array<String> keywords = {scratch};
|
||||
keywords.add("Keyword"_s);
|
||||
keywords.add("for"_s);
|
||||
keywords.add("if"_s);
|
||||
keywords.add("while"_s);
|
||||
keywords.add("switch"_s);
|
||||
|
||||
Lexer lexer = lex_make();
|
||||
Lexer lexer = lex_make(scratch, scratch);
|
||||
lex_set_keywords(&lexer, keywords);
|
||||
lex_restream(&lexer, test, "Test1"_s);
|
||||
Array<Token> array = lexer.tokens;
|
||||
Array<Token> arr = lexer.tokens;
|
||||
|
||||
Token_Kind kind[] = {
|
||||
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_Equals, TK_Integer, TK_Integer, TK_Integer,
|
||||
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
|
||||
TK_ColonAssign, TK_End
|
||||
TK_Colon, TK_Assign, TK_End
|
||||
};
|
||||
String strs[] = {
|
||||
"Keyword"_s, "\n "_s, "18446744073709551616"_s,"{"_s,"}"_s,")"_s,"("_s,
|
||||
@@ -554,18 +554,18 @@ lex_test(){ Set_Scratch();
|
||||
"..."_s,"."_s,"->"_s,","_s,"::"_s,":"_s,
|
||||
"Thing"_s,"Thingy"_s,"Test_Meme"_s, "+="_s,"-="_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[] = {
|
||||
42524, 4294967295, 18446744073709551615llu
|
||||
};
|
||||
|
||||
int ui = 0;
|
||||
For(array, t, i){
|
||||
assert(t->kind == kind[i]);
|
||||
assert(string_compare(t->string, strs[i]));
|
||||
if(t->kind == TK_Integer){
|
||||
assert(t->int_val == vals[ui++]);
|
||||
For(arr){
|
||||
assert(it->kind == kind[i]);
|
||||
assert(string_compare(it->string, strs[i]));
|
||||
if(it->kind == TK_Integer){
|
||||
assert(it->int_val == vals[ui++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,7 +603,6 @@ token_kind_string(Token_Kind kind){
|
||||
case TK_GreaterThen: return ">"_s;
|
||||
case TK_Colon: return ":"_s;
|
||||
case TK_Assign: return "="_s;
|
||||
case TK_ColonAssign: return ":="_s;
|
||||
case TK_DivAssign: return "/="_s;
|
||||
case TK_MulAssign: return "*="_s;
|
||||
case TK_ModAssign: return "%="_s;
|
||||
@@ -629,6 +628,7 @@ token_kind_string(Token_Kind kind){
|
||||
case TK_LeftShift: return "<<"_s;
|
||||
case TK_RightShift: return ">>"_s;
|
||||
case TK_Arrow: return "->"_s;
|
||||
case TK_NewLine: return "NewLine"_s;
|
||||
case TK_ExprSizeof: return "sizeof"_s;
|
||||
case TK_DocComment: return "DocComment"_s;
|
||||
case TK_Comment: return "Comment"_s;
|
||||
|
||||
201
new_parse.cpp
201
new_parse.cpp
@@ -1,22 +1,22 @@
|
||||
|
||||
function Token *
|
||||
token_get(S64 i = 0){ Get_Ctx(Parse_Ctx);
|
||||
i += ctx->token_iter;
|
||||
if(i >= ctx->tokens.len){
|
||||
return &ctx->empty_token;
|
||||
token_get(S64 i = 0){
|
||||
i += pctx->token_iter;
|
||||
if(i >= pctx->tokens.len){
|
||||
return &pctx->empty_token;
|
||||
}
|
||||
Token *result = &ctx->tokens[i];
|
||||
Token *result = &pctx->tokens[i];
|
||||
if(result->kind == TK_NewLine){
|
||||
ctx->indent = result->indent;
|
||||
pctx->indent = result->indent;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_next(){ Get_Ctx(Parse_Ctx);
|
||||
token_next(){
|
||||
Token *token = token_get();
|
||||
ctx->token_iter++;
|
||||
pctx->token_iter++;
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ token_match_keyword(Intern_String string){
|
||||
|
||||
function void
|
||||
parsing_error(Token *token, const char *str, ...){
|
||||
Set_Scratch();
|
||||
STRING_FMT(imp_get(), str, string);
|
||||
Scratch scratch;
|
||||
STRING_FMT(scratch, str, string);
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
printf("\nError: %s", string.str);
|
||||
@@ -122,6 +122,41 @@ Compound literals
|
||||
- { }
|
||||
*/
|
||||
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 *
|
||||
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_Identifier: return ast_expr_identifier(token, token->intern_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;}
|
||||
default: parsing_error(token, "Unexpected token of kind: [%s] in expression", token_kind_string(token->kind).str); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function S64
|
||||
op_precedence(Token_Kind kind){ Get_Ctx(Parse_Ctx);
|
||||
S64 result = ctx->pt[kind];
|
||||
op_precedence(Token_Kind kind){
|
||||
S64 result = pctx->pt[kind];
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -183,22 +233,22 @@ expr_eval(Ast_Expr *expr){
|
||||
}
|
||||
|
||||
#define TEST_PARSER() \
|
||||
Set_Scratch(); \
|
||||
Scratch scratch(thread_ctx.scratch);\
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(); \
|
||||
Set_Ctx(&ctx, Parse_Ctx_ID)
|
||||
ctx.init(scratch, scratch); \
|
||||
pctx = &ctx
|
||||
|
||||
function void
|
||||
test_parse_expr(){
|
||||
TEST_PARSER();
|
||||
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+5"_s, 4*5+5});
|
||||
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);
|
||||
Ast_Expr *result = parse_expr();
|
||||
S64 val = expr_eval(result);
|
||||
@@ -209,38 +259,115 @@ test_parse_expr(){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parsing declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
function Ast_Decl *
|
||||
parse_decl(){Get_Ctx(Parse_Ctx);
|
||||
Ast_Decl *result = 0;
|
||||
Token *token = token_match(TK_Identifier);
|
||||
if(token){
|
||||
if(token_match(TK_ColonAssign)){
|
||||
if(ctx->indent != 0)
|
||||
parsing_error(token, "Top level declarations shouldn't be indented");
|
||||
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_decl_var(token, 0, token->intern_val, expr);
|
||||
function Ast_Typespec *
|
||||
parse_optional_type(){
|
||||
Ast_Typespec *result = 0;
|
||||
if(token_match(TK_Colon)) result = parse_typespec();
|
||||
return result;
|
||||
}
|
||||
else parsing_error(token, "Encountered unexpected token while parsing a top level declarations");
|
||||
|
||||
function Ast_Typespec *
|
||||
parse_typespec_function(Token *token){
|
||||
Scratch scratch;
|
||||
Array<Ast_Typespec *> args = {scratch};
|
||||
if(!token_is(TK_CloseParen)) {
|
||||
for(;;) {
|
||||
args.add(parse_typespec());
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
Ast_Typespec *ret = parse_optional_type();
|
||||
Ast_Typespec *result = ast_typespec_func(token, ret, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
// [10]*int - Array of 10 pointers to ints
|
||||
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;
|
||||
}
|
||||
|
||||
function Ast_Package *
|
||||
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_match(TK_NewLine));
|
||||
Ast_Decl *decl = parse_decl();
|
||||
if(!decl) break;
|
||||
result->decls.add(decl);
|
||||
decls.add(decl);
|
||||
}
|
||||
Ast_Package *result = ast_package(token, token->file, decls);
|
||||
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{
|
||||
TYPE_None,
|
||||
TYPE_Null,
|
||||
TYPE_Int,
|
||||
TYPE_Bool,
|
||||
TYPE_Unsigned,
|
||||
TYPE_String,
|
||||
TYPE_Void,
|
||||
TYPE_Pointer,
|
||||
@@ -12,6 +14,22 @@ enum Type_Kind{
|
||||
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{
|
||||
Type_Kind kind;
|
||||
SizeU size;
|
||||
@@ -32,13 +50,19 @@ struct Type{
|
||||
const SizeU pointer_size = sizeof(SizeU);
|
||||
const SizeU pointer_align = __alignof(SizeU);
|
||||
|
||||
global Type type__null = {TYPE_Null};
|
||||
global Type type__void = {TYPE_Void};
|
||||
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__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
||||
|
||||
global Type *type_void = &type__void;
|
||||
global Type *type_int = &type__int;
|
||||
global Type *type_unsigned = &type__unsigned;
|
||||
global Type *type_string = &type__string;
|
||||
global Type *type_bool = &type__bool;
|
||||
global Type *type_null = &type__null;
|
||||
|
||||
function Type *
|
||||
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){
|
||||
@@ -58,12 +82,11 @@ type_copy(Allocator *a, Type *type){
|
||||
|
||||
function Type *
|
||||
type_pointer(Type *base){
|
||||
Get_Ctx(Parse_Ctx);
|
||||
Type *result = (Type *)map_get(&ctx->type_map, (void *)base);
|
||||
Type *result = (Type *)map_get(&pctx->type_map, (void *)base);
|
||||
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;
|
||||
map_insert(&ctx->type_map, base, result);
|
||||
map_insert(&pctx->type_map, base, result);
|
||||
}
|
||||
assert(result->kind == TYPE_Pointer);
|
||||
return result;
|
||||
@@ -71,9 +94,8 @@ type_pointer(Type *base){
|
||||
|
||||
function Type *
|
||||
type_array(Type *base, SizeU size){
|
||||
Get_Ctx(Parse_Ctx);
|
||||
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){
|
||||
assert(result->kind == TYPE_Array);
|
||||
assert(result->arr.size == size);
|
||||
@@ -81,44 +103,40 @@ type_array(Type *base, SizeU size){
|
||||
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.size = size;
|
||||
map_insert_u64(&ctx->type_map, hash, result);
|
||||
map_insert_u64(&pctx->type_map, hash, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Type *
|
||||
type_function(Type *ret, Array<Type *> args){
|
||||
Get_Ctx(Parse_Ctx);
|
||||
|
||||
U64 hash = hash_ptr(ret);
|
||||
IFor(args){
|
||||
hash = hash_mix(hash, hash_ptr(*it));
|
||||
}
|
||||
For(args) hash = hash_mix(hash, hash_ptr(*it));
|
||||
Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
|
||||
|
||||
Type *result = (Type *)map_get_u64(&ctx->type_map, hash);
|
||||
if(result){
|
||||
assert(result->kind == TYPE_Func);
|
||||
assert(result->func.ret == ret);
|
||||
assert(result->func.args.len == args.len);
|
||||
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.args = args.copy(&ctx->ast_arena);
|
||||
map_insert_u64(&ctx->type_map, hash, result);
|
||||
result->func.args = args.tight_copy(pctx->perm);
|
||||
map_insert_u64(&pctx->type_map, hash, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
test_types(){
|
||||
Set_Backup_Scratch();
|
||||
Set_Scratch();
|
||||
Scratch scratch;
|
||||
Parse_Ctx ctx = {};
|
||||
Set_Ctx(&ctx, Parse_Ctx_ID);
|
||||
ctx.ast_arena = thread_ctx.scratch[1];
|
||||
ctx.init(scratch, scratch);
|
||||
pctx = &ctx;
|
||||
|
||||
Type *array_type1 = 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_type4);
|
||||
|
||||
Array<Type*> types = {};
|
||||
Array<Type*> types = {scratch};
|
||||
types.add(type_array(type_int, 32));
|
||||
Type *func_type1 = type_function(types[0], types);
|
||||
Type *func_type2 = type_function(types[0], types);
|
||||
assert(func_type1 == func_type2);
|
||||
|
||||
Array<Type*> types2 = {};
|
||||
Array<Type*> types2 = {scratch};
|
||||
{
|
||||
types2.add(type_array(type_int, 32));
|
||||
types2.add(type_int);
|
||||
|
||||
17
os_win32.c
17
os_win32.c
@@ -1,23 +1,6 @@
|
||||
function S32 os_main();
|
||||
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
|
||||
get_align_offset(SizeU size, SizeU align){
|
||||
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